function shareArticle()
 {
     $param = db_escape_string($_REQUEST['param']);
     $result = db_query($this->link, "SELECT uuid, ref_id FROM ttrss_user_entries WHERE int_id = '{$param}'\n\t\t\tAND owner_uid = " . $_SESSION['uid']);
     if (db_num_rows($result) == 0) {
         print "Article not found.";
     } else {
         $uuid = db_fetch_result($result, 0, "uuid");
         $ref_id = db_fetch_result($result, 0, "ref_id");
         if (!$uuid) {
             $uuid = db_escape_string(sha1(uniqid(rand(), true)));
             db_query($this->link, "UPDATE ttrss_user_entries SET uuid = '{$uuid}' WHERE int_id = '{$param}'\n\t\t\t\t\tAND owner_uid = " . $_SESSION['uid']);
         }
         print __("You can share this article by the following unique URL:");
         $url_path = get_self_url_prefix();
         $url_path .= "/public.php?op=share&key={$uuid}";
         print "<div class=\"tagCloudContainer\">";
         print "<a id='pub_opml_url' href='{$url_path}' target='_blank'>{$url_path}</a>";
         print "</div>";
         /* if (!label_find_id($this->link, __('Shared'), $_SESSION["uid"]))
         				label_create($this->link, __('Shared'), $_SESSION["uid"]);
         
         			label_add_article($this->link, $ref_id, __('Shared'), $_SESSION['uid']); */
     }
     print "<div align='center'>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('shareArticleDlg').hide()\">" . __('Close this window') . "</button>";
     print "</div>";
 }
 function hook_prefs_tab($args)
 {
     if ($args != "prefPrefs") {
         return;
     }
     print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __("Fever Emulation") . "\">";
     print "<h3>" . __("Fever Emulation") . "</h3>";
     print "<p>" . __("Since the Fever API uses a different authentication mechanism to Tiny Tiny RSS, you must set a separate password to login. This password may be the same as your Tiny Tiny RSS password.") . "</p>";
     print "<p>" . __("Set a password to login with Fever:") . "</p>";
     print "<form dojoType=\"dijit.form.Form\">";
     print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">\n\t\t\tevt.preventDefault();\n\t\t\tif (this.validate()) {\n\t\t\t\tnew Ajax.Request('backend.php', {\n\t\t\t\t\tparameters: dojo.objectToQuery(this.getValues()),\n\t\t\t\t\tonComplete: function(transport) {\n\t\t\t\t\t\tnotify_info(transport.responseText);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t//this.reset();\n\t\t\t}\n\t\t\t</script>";
     print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pluginhandler\" />";
     print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"save\" />";
     print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"fever\" />";
     print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" type=\"password\" name=\"password\" />";
     print "<button dojoType=\"dijit.form.Button\" type=\"submit\">" . __("Set Password") . "</button>";
     print "</form>";
     print "<p>" . __("To login with the Fever API, set your server details in your favourite RSS application to: ") . get_self_url_prefix() . "/plugins/fever/" . "</p>";
     print "<p>" . __("Additional details can be found at ") . "<a href=\"http://www.feedafever.com/api\" target=\"_blank\">http://www.feedafever.com/api</a></p>";
     print "<p>" . __("Note: Due to the limitations of the API and some RSS clients (for example, Reeder on iOS), some features are unavailable: \"Special\" Feeds (Published / Tags / Labels / Fresh / Recent), Nested Categories (hierarchy is flattened)") . "</p>";
     print "</div>";
 }
 function subscribe2()
 {
     $feed_url = $this->dbh->escape_string(trim($_REQUEST["feed_url"]));
     $cat_id = $this->dbh->escape_string($_REQUEST["cat_id"]);
     $from = $this->dbh->escape_string($_REQUEST["from"]);
     $feed_urls = array();
     /* only read authentication information from POST */
     $auth_login = $this->dbh->escape_string(trim($_POST["auth_login"]));
     $auth_pass = $this->dbh->escape_string(trim($_POST["auth_pass"]));
     $rc = subscribe_to_feed($feed_url, $cat_id, $auth_login, $auth_pass);
     switch ($rc) {
         case 1:
             print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
             break;
         case 2:
             print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
             break;
         case 3:
             print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
             break;
         case 0:
             print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
             break;
         case 4:
             print_notice(__("Multiple feed URLs found."));
             $contents = @fetch_file_contents($url, false, $auth_login, $auth_pass);
             if (is_html($contents)) {
                 $feed_urls = get_feeds_from_html($url, $contents);
             }
             break;
         case 5:
             print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
             break;
     }
     if ($feed_urls) {
         print "<form action=\"backend.php\">";
         print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
         print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
         print "<input type=\"hidden\" name=\"method\" value=\"add\">";
         print "<select name=\"feed_url\">";
         foreach ($feed_urls as $url => $name) {
             $url = htmlspecialchars($url);
             $name = htmlspecialchars($name);
             print "<option value=\"{$url}\">{$name}</option>";
         }
         print "<input type=\"submit\" value=\"" . __("Subscribe to selected feed") . "\">";
         print "</form>";
     }
     $tp_uri = get_self_url_prefix() . "/prefs.php";
     $tt_uri = get_self_url_prefix();
     if ($rc <= 2) {
         $result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE\n\t\t\t\tfeed_url = '{$feed_url}' AND owner_uid = " . $_SESSION["uid"]);
         $feed_id = $this->dbh->fetch_result($result, 0, "id");
     } else {
         $feed_id = 0;
     }
     print "<p>";
     if ($feed_id) {
         print "<form method=\"GET\" style='display: inline'\n\t\t\t\taction=\"{$tp_uri}\">\n\t\t\t\t<input type=\"hidden\" name=\"tab\" value=\"feedConfig\">\n\t\t\t\t<input type=\"hidden\" name=\"method\" value=\"editFeed\">\n\t\t\t\t<input type=\"hidden\" name=\"methodparam\" value=\"{$feed_id}\">\n\t\t\t\t<input type=\"submit\" value=\"" . __("Edit subscription options") . "\">\n\t\t\t\t</form>";
     }
     print "<form style='display: inline' method=\"GET\" action=\"{$tt_uri}\">\n\t\t\t<input type=\"submit\" value=\"" . __("Return to Tiny Tiny RSS") . "\">\n\t\t\t</form></p>";
     print "</body></html>";
 }
function update_rss_feed($link, $feed, $ignore_daemon = false, $no_cache = false, $override_url = false)
{
    require_once "lib/simplepie/simplepie.inc";
    $debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
    if ($debug_enabled) {
        _debug("update_rss_feed: start");
    }
    $result = db_query($link, "SELECT id,update_interval,auth_login,\n\t\t\tfeed_url,auth_pass,cache_images,last_updated,\n\t\t\tmark_unread_on_update, owner_uid,\n\t\t\tpubsub_state\n\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
    if (db_num_rows($result) == 0) {
        if ($debug_enabled) {
            _debug("update_rss_feed: feed {$feed} NOT FOUND/SKIPPED");
        }
        return false;
    }
    $last_updated = db_fetch_result($result, 0, "last_updated");
    $owner_uid = db_fetch_result($result, 0, "owner_uid");
    $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
    $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
    db_query($link, "UPDATE ttrss_feeds SET last_update_started = NOW()\n\t\t\tWHERE id = '{$feed}'");
    $auth_login = db_fetch_result($result, 0, "auth_login");
    $auth_pass = db_fetch_result($result, 0, "auth_pass");
    $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
    $fetch_url = db_fetch_result($result, 0, "feed_url");
    $feed = db_escape_string($feed);
    /* if ($auth_login && $auth_pass ){
    			$url_parts = array();
    			preg_match("/(^[^:]*):\/\/(.*)/", $fetch_url, $url_parts);
    
    			if ($url_parts[1] && $url_parts[2]) {
    				$fetch_url = $url_parts[1] . "://$auth_login:$auth_pass@" . $url_parts[2];
    			}
    		} */
    if ($override_url) {
        $fetch_url = $override_url;
    }
    if ($debug_enabled) {
        _debug("update_rss_feed: fetching [{$fetch_url}]...");
    }
    // Ignore cache if new feed or manual update.
    $cache_age = is_null($last_updated) || $last_updated == '1970-01-01 00:00:00' ? -1 : get_feed_update_interval($link, $feed) * 60;
    $simplepie_cache_dir = CACHE_DIR . "/simplepie";
    if (!is_dir($simplepie_cache_dir)) {
        mkdir($simplepie_cache_dir);
    }
    $feed_data = fetch_file_contents($fetch_url, false, $auth_login, $auth_pass, false, $no_cache ? 15 : 45);
    if (!$feed_data) {
        global $fetch_last_error;
        if ($debug_enabled) {
            _debug("update_rss_feed: unable to fetch: {$fetch_last_error}");
        }
        $error_escaped = db_escape_string($fetch_last_error);
        db_query($link, "UPDATE ttrss_feeds SET last_error = '{$error_escaped}',\n\t\t\t\t\tlast_updated = NOW() WHERE id = '{$feed}'");
        return;
    }
    $pluginhost = new PluginHost($link);
    $pluginhost->set_debug($debug_enabled);
    $user_plugins = get_pref($link, "_ENABLED_PLUGINS", $owner_uid);
    $pluginhost->load(PLUGINS, $pluginhost::KIND_ALL);
    $pluginhost->load($user_plugins, $pluginhost::KIND_USER, $owner_uid);
    $pluginhost->load_data();
    foreach ($pluginhost->get_hooks($pluginhost::HOOK_FEED_FETCHED) as $plugin) {
        $feed_data = $plugin->hook_feed_fetched($feed_data);
    }
    if ($debug_enabled) {
        _debug("update_rss_feed: fetch done, parsing...");
    }
    $rss = new SimplePie();
    $rss->set_sanitize_class("SanitizeDummy");
    // simplepie ignores the above and creates default sanitizer anyway,
    // so let's override it...
    $rss->sanitize = new SanitizeDummy();
    $rss->set_output_encoding('UTF-8');
    $rss->set_raw_data($feed_data);
    if ($debug_enabled) {
        _debug("feed update interval (sec): " . get_feed_update_interval($link, $feed) * 60);
    }
    $rss->enable_cache(!$no_cache);
    if (!$no_cache) {
        $rss->set_cache_location($simplepie_cache_dir);
        $rss->set_cache_duration($cache_age);
    }
    @$rss->init();
    //		print_r($rss);
    $feed = db_escape_string($feed);
    if (!$rss->error()) {
        // We use local pluginhost here because we need to load different per-user feed plugins
        $pluginhost->run_hooks($pluginhost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
        if ($debug_enabled) {
            _debug("update_rss_feed: processing feed data...");
        }
        //			db_query($link, "BEGIN");
        if (DB_TYPE == "pgsql") {
            $favicon_interval_qpart = "favicon_last_checked < NOW() - INTERVAL '12 hour'";
        } else {
            $favicon_interval_qpart = "favicon_last_checked < DATE_SUB(NOW(), INTERVAL 12 HOUR)";
        }
        $result = db_query($link, "SELECT title,site_url,owner_uid,\n\t\t\t\t(favicon_last_checked IS NULL OR {$favicon_interval_qpart}) AS\n\t\t\t\t\t\tfavicon_needs_check\n\t\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
        $registered_title = db_fetch_result($result, 0, "title");
        $orig_site_url = db_fetch_result($result, 0, "site_url");
        $favicon_needs_check = sql_bool_to_bool(db_fetch_result($result, 0, "favicon_needs_check"));
        $owner_uid = db_fetch_result($result, 0, "owner_uid");
        $site_url = db_escape_string(mb_substr(rewrite_relative_url($fetch_url, $rss->get_link()), 0, 245));
        if ($debug_enabled) {
            _debug("update_rss_feed: checking favicon...");
        }
        if ($favicon_needs_check) {
            check_feed_favicon($site_url, $feed, $link);
            db_query($link, "UPDATE ttrss_feeds SET favicon_last_checked = NOW()\n\t\t\t\t\tWHERE id = '{$feed}'");
        }
        if (!$registered_title || $registered_title == "[Unknown]") {
            $feed_title = db_escape_string($rss->get_title());
            if ($debug_enabled) {
                _debug("update_rss_feed: registering title: {$feed_title}");
            }
            db_query($link, "UPDATE ttrss_feeds SET\n\t\t\t\t\ttitle = '{$feed_title}' WHERE id = '{$feed}'");
        }
        if ($site_url && $orig_site_url != $site_url) {
            db_query($link, "UPDATE ttrss_feeds SET\n\t\t\t\t\tsite_url = '{$site_url}' WHERE id = '{$feed}'");
        }
        if ($debug_enabled) {
            _debug("update_rss_feed: loading filters & labels...");
        }
        $filters = load_filters($link, $feed, $owner_uid);
        $labels = get_all_labels($link, $owner_uid);
        if ($debug_enabled) {
            //print_r($filters);
            _debug("update_rss_feed: " . count($filters) . " filters loaded.");
        }
        $items = $rss->get_items();
        if (!is_array($items)) {
            if ($debug_enabled) {
                _debug("update_rss_feed: no articles found.");
            }
            db_query($link, "UPDATE ttrss_feeds\n\t\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
            return;
            // no articles
        }
        if ($pubsub_state != 2 && PUBSUBHUBBUB_ENABLED) {
            if ($debug_enabled) {
                _debug("update_rss_feed: checking for PUSH hub...");
            }
            $feed_hub_url = false;
            $links = $rss->get_links('hub');
            if ($links && is_array($links)) {
                foreach ($links as $l) {
                    $feed_hub_url = $l;
                    break;
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: feed hub url: {$feed_hub_url}");
            }
            if ($feed_hub_url && function_exists('curl_init') && !ini_get("open_basedir")) {
                require_once 'lib/pubsubhubbub/subscriber.php';
                $callback_url = get_self_url_prefix() . "/public.php?op=pubsub&id={$feed}";
                $s = new Subscriber($feed_hub_url, $callback_url);
                $rc = $s->subscribe($fetch_url);
                if ($debug_enabled) {
                    _debug("update_rss_feed: feed hub url found, subscribe request sent.");
                }
                db_query($link, "UPDATE ttrss_feeds SET pubsub_state = 1\n\t\t\t\t\t\tWHERE id = '{$feed}'");
            }
        }
        if ($debug_enabled) {
            _debug("update_rss_feed: processing articles...");
        }
        foreach ($items as $item) {
            if ($_REQUEST['xdebug'] == 3) {
                print_r($item);
            }
            $entry_guid = $item->get_id();
            if (!$entry_guid) {
                $entry_guid = $item->get_link();
            }
            if (!$entry_guid) {
                $entry_guid = make_guid_from_title($item->get_title());
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: guid {$entry_guid}");
            }
            if (!$entry_guid) {
                continue;
            }
            $entry_guid = "{$owner_uid},{$entry_guid}";
            $entry_timestamp = "";
            $entry_timestamp = strtotime($item->get_date());
            if ($entry_timestamp == -1 || !$entry_timestamp) {
                $entry_timestamp = time();
                $no_orig_date = 'true';
            } else {
                $no_orig_date = 'false';
            }
            $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
            if ($debug_enabled) {
                _debug("update_rss_feed: date {$entry_timestamp} [{$entry_timestamp_fmt}]");
            }
            $entry_title = $item->get_title();
            $entry_link = rewrite_relative_url($site_url, $item->get_link());
            if ($debug_enabled) {
                _debug("update_rss_feed: title {$entry_title}");
                _debug("update_rss_feed: link {$entry_link}");
            }
            if (!$entry_title) {
                $entry_title = date("Y-m-d H:i:s", $entry_timestamp);
            }
            $entry_content = $item->get_content();
            if (!$entry_content) {
                $entry_content = $item->get_description();
            }
            if ($_REQUEST["xdebug"] == 2) {
                print "update_rss_feed: content: ";
                print $entry_content;
                print "\n";
            }
            $entry_comments = $item->data["comments"];
            if ($item->get_author()) {
                $entry_author_item = $item->get_author();
                $entry_author = $entry_author_item->get_name();
                if (!$entry_author) {
                    $entry_author = $entry_author_item->get_email();
                }
                $entry_author = db_escape_string($entry_author);
            }
            $entry_guid = db_escape_string(mb_substr($entry_guid, 0, 245));
            $entry_comments = db_escape_string(mb_substr($entry_comments, 0, 245));
            $entry_author = db_escape_string(mb_substr($entry_author, 0, 245));
            $num_comments = $item->get_item_tags('http://purl.org/rss/1.0/modules/slash/', 'comments');
            if (is_array($num_comments) && is_array($num_comments[0])) {
                $num_comments = (int) $num_comments[0]["data"];
            } else {
                $num_comments = 0;
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: num_comments: {$num_comments}");
                _debug("update_rss_feed: looking for tags [1]...");
            }
            // parse <category> entries into tags
            $additional_tags = array();
            $additional_tags_src = $item->get_categories();
            if (is_array($additional_tags_src)) {
                foreach ($additional_tags_src as $tobj) {
                    array_push($additional_tags, $tobj->get_term());
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: category tags:");
                print_r($additional_tags);
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: looking for tags [2]...");
            }
            $entry_tags = array_unique($additional_tags);
            for ($i = 0; $i < count($entry_tags); $i++) {
                $entry_tags[$i] = mb_strtolower($entry_tags[$i], 'utf-8');
            }
            if ($debug_enabled) {
                //_debug("update_rss_feed: unfiltered tags found:");
                //print_r($entry_tags);
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: done collecting data.");
            }
            // TODO: less memory-hungry implementation
            if ($debug_enabled) {
                _debug("update_rss_feed: applying plugin filters..");
            }
            // FIXME not sure if owner_uid is a good idea here, we may have a base entry without user entry (?)
            $result = db_query($link, "SELECT plugin_data,title,content,link,tag_cache,author FROM ttrss_entries, ttrss_user_entries\n\t\t\t\t\tWHERE ref_id = id AND guid = '" . db_escape_string($entry_guid) . "' AND owner_uid = {$owner_uid}");
            if (db_num_rows($result) != 0) {
                $entry_plugin_data = db_fetch_result($result, 0, "plugin_data");
                $stored_article = array("title" => db_fetch_result($result, 0, "title"), "content" => db_fetch_result($result, 0, "content"), "link" => db_fetch_result($result, 0, "link"), "tags" => explode(",", db_fetch_result($result, 0, "tag_cache")), "author" => db_fetch_result($result, 0, "author"));
            } else {
                $entry_plugin_data = "";
                $stored_article = array();
            }
            $article = array("owner_uid" => $owner_uid, "guid" => $entry_guid, "title" => $entry_title, "content" => $entry_content, "link" => $entry_link, "tags" => $entry_tags, "plugin_data" => $entry_plugin_data, "author" => $entry_author, "stored" => $stored_article);
            foreach ($pluginhost->get_hooks($pluginhost::HOOK_ARTICLE_FILTER) as $plugin) {
                $article = $plugin->hook_article_filter($article);
            }
            $entry_tags = $article["tags"];
            $entry_guid = db_escape_string($entry_guid);
            $entry_content = db_escape_string($article["content"], false);
            $entry_title = db_escape_string($article["title"]);
            $entry_author = db_escape_string($article["author"]);
            $entry_link = db_escape_string($article["link"]);
            $entry_plugin_data = db_escape_string($article["plugin_data"]);
            if ($debug_enabled) {
                _debug("update_rss_feed: plugin data: {$entry_plugin_data}");
            }
            if ($cache_images && is_writable(CACHE_DIR . '/images')) {
                $entry_content = cache_images($entry_content, $site_url, $debug_enabled);
            }
            $content_hash = "SHA1:" . sha1($entry_content);
            db_query($link, "BEGIN");
            $result = db_query($link, "SELECT id FROM\tttrss_entries\n\t\t\t\t\tWHERE guid = '{$entry_guid}'");
            if (db_num_rows($result) == 0) {
                if ($debug_enabled) {
                    _debug("update_rss_feed: base guid [{$entry_guid}] not found");
                }
                // base post entry does not exist, create it
                $result = db_query($link, "INSERT INTO ttrss_entries\n\t\t\t\t\t\t\t(title,\n\t\t\t\t\t\t\tguid,\n\t\t\t\t\t\t\tlink,\n\t\t\t\t\t\t\tupdated,\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tcontent_hash,\n\t\t\t\t\t\t\tcached_content,\n\t\t\t\t\t\t\tno_orig_date,\n\t\t\t\t\t\t\tdate_updated,\n\t\t\t\t\t\t\tdate_entered,\n\t\t\t\t\t\t\tcomments,\n\t\t\t\t\t\t\tnum_comments,\n\t\t\t\t\t\t\tplugin_data,\n\t\t\t\t\t\t\tauthor)\n\t\t\t\t\t\tVALUES\n\t\t\t\t\t\t\t('{$entry_title}',\n\t\t\t\t\t\t\t'{$entry_guid}',\n\t\t\t\t\t\t\t'{$entry_link}',\n\t\t\t\t\t\t\t'{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t'{$entry_content}',\n\t\t\t\t\t\t\t'{$content_hash}',\n\t\t\t\t\t\t\t'',\n\t\t\t\t\t\t\t{$no_orig_date},\n\t\t\t\t\t\t\tNOW(),\n\t\t\t\t\t\t\tNOW(),\n\t\t\t\t\t\t\t'{$entry_comments}',\n\t\t\t\t\t\t\t'{$num_comments}',\n\t\t\t\t\t\t\t'{$entry_plugin_data}',\n\t\t\t\t\t\t\t'{$entry_author}')");
                $article_labels = array();
            } else {
                // we keep encountering the entry in feeds, so we need to
                // update date_updated column so that we don't get horrible
                // dupes when the entry gets purged and reinserted again e.g.
                // in the case of SLOW SLOW OMG SLOW updating feeds
                $base_entry_id = db_fetch_result($result, 0, "id");
                db_query($link, "UPDATE ttrss_entries SET date_updated = NOW()\n\t\t\t\t\t\tWHERE id = '{$base_entry_id}'");
                $article_labels = get_article_labels($link, $base_entry_id, $owner_uid);
            }
            // now it should exist, if not - bad luck then
            $result = db_query($link, "SELECT\n\t\t\t\t\t\tid,content_hash,no_orig_date,title,plugin_data,\n\t\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(date_updated,1,19) as date_updated,\n\t\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(updated,1,19) as updated,\n\t\t\t\t\t\tnum_comments\n\t\t\t\t\tFROM\n\t\t\t\t\t\tttrss_entries\n\t\t\t\t\tWHERE guid = '{$entry_guid}'");
            $entry_ref_id = 0;
            $entry_int_id = 0;
            if (db_num_rows($result) == 1) {
                if ($debug_enabled) {
                    _debug("update_rss_feed: base guid [{$entry_guid}] found, checking for user record");
                }
                // this will be used below in update handler
                $orig_content_hash = db_fetch_result($result, 0, "content_hash");
                $orig_title = db_fetch_result($result, 0, "title");
                $orig_num_comments = db_fetch_result($result, 0, "num_comments");
                $orig_date_updated = strtotime(db_fetch_result($result, 0, "date_updated"));
                $orig_plugin_data = db_fetch_result($result, 0, "plugin_data");
                $ref_id = db_fetch_result($result, 0, "id");
                $entry_ref_id = $ref_id;
                // check for user post link to main table
                // do we allow duplicate posts with same GUID in different feeds?
                if (get_pref($link, "ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
                    $dupcheck_qpart = "AND (feed_id = '{$feed}' OR feed_id IS NULL)";
                } else {
                    $dupcheck_qpart = "";
                }
                /* Collect article tags here so we could filter by them: */
                $article_filters = get_article_filters($filters, $entry_title, $entry_content, $entry_link, $entry_timestamp, $entry_author, $entry_tags);
                if ($debug_enabled) {
                    _debug("update_rss_feed: article filters: ");
                    if (count($article_filters) != 0) {
                        print_r($article_filters);
                    }
                }
                if (find_article_filter($article_filters, "filter")) {
                    db_query($link, "COMMIT");
                    // close transaction in progress
                    continue;
                }
                $score = calculate_article_score($article_filters);
                if ($debug_enabled) {
                    _debug("update_rss_feed: initial score: {$score}");
                }
                $query = "SELECT ref_id, int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}'\n\t\t\t\t\t\t\t{$dupcheck_qpart}";
                //					if ($_REQUEST["xdebug"]) print "$query\n";
                $result = db_query($link, $query);
                // okay it doesn't exist - create user entry
                if (db_num_rows($result) == 0) {
                    if ($debug_enabled) {
                        _debug("update_rss_feed: user record not found, creating...");
                    }
                    if ($score >= -500 && !find_article_filter($article_filters, 'catchup')) {
                        $unread = 'true';
                        $last_read_qpart = 'NULL';
                    } else {
                        $unread = 'false';
                        $last_read_qpart = 'NOW()';
                    }
                    if (find_article_filter($article_filters, 'mark') || $score > 1000) {
                        $marked = 'true';
                    } else {
                        $marked = 'false';
                    }
                    if (find_article_filter($article_filters, 'publish')) {
                        $published = 'true';
                    } else {
                        $published = 'false';
                    }
                    // N-grams
                    if (DB_TYPE == "pgsql" and defined('_NGRAM_TITLE_DUPLICATE_THRESHOLD')) {
                        $result = db_query($link, "SELECT COUNT(*) AS similar FROM\n\t\t\t\t\t\t\t\t\tttrss_entries,ttrss_user_entries\n\t\t\t\t\t\t\t\tWHERE ref_id = id AND updated >= NOW() - INTERVAL '7 day'\n\t\t\t\t\t\t\t\t\tAND similarity(title, '{$entry_title}') >= " . _NGRAM_TITLE_DUPLICATE_THRESHOLD . "\n\t\t\t\t\t\t\t\t\tAND owner_uid = {$owner_uid}");
                        $ngram_similar = db_fetch_result($result, 0, "similar");
                        if ($debug_enabled) {
                            _debug("update_rss_feed: N-gram similar results: {$ngram_similar}");
                        }
                        if ($ngram_similar > 0) {
                            $unread = 'false';
                        }
                    }
                    $result = db_query($link, "INSERT INTO ttrss_user_entries\n\t\t\t\t\t\t\t\t(ref_id, owner_uid, feed_id, unread, last_read, marked,\n\t\t\t\t\t\t\t\t\tpublished, score, tag_cache, label_cache, uuid)\n\t\t\t\t\t\t\tVALUES ('{$ref_id}', '{$owner_uid}', '{$feed}', {$unread},\n\t\t\t\t\t\t\t\t{$last_read_qpart}, {$marked}, {$published}, '{$score}', '', '', '')");
                    if (PUBSUBHUBBUB_HUB && $published == 'true') {
                        $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key($link, -2, false, $owner_uid);
                        $p = new Publisher(PUBSUBHUBBUB_HUB);
                        $pubsub_result = $p->publish_update($rss_link);
                    }
                    $result = db_query($link, "SELECT int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}' AND\n\t\t\t\t\t\t\t\tfeed_id = '{$feed}' LIMIT 1");
                    if (db_num_rows($result) == 1) {
                        $entry_int_id = db_fetch_result($result, 0, "int_id");
                    }
                } else {
                    if ($debug_enabled) {
                        _debug("update_rss_feed: user record FOUND");
                    }
                    $entry_ref_id = db_fetch_result($result, 0, "ref_id");
                    $entry_int_id = db_fetch_result($result, 0, "int_id");
                }
                if ($debug_enabled) {
                    _debug("update_rss_feed: RID: {$entry_ref_id}, IID: {$entry_int_id}");
                }
                $post_needs_update = false;
                $update_insignificant = false;
                if ($orig_num_comments != $num_comments) {
                    $post_needs_update = true;
                    $update_insignificant = true;
                }
                if ($entry_plugin_data != $orig_plugin_data) {
                    $post_needs_update = true;
                    $update_insignificant = true;
                }
                if ($content_hash != $orig_content_hash) {
                    $post_needs_update = true;
                    $update_insignificant = false;
                }
                if (db_escape_string($orig_title) != $entry_title) {
                    $post_needs_update = true;
                    $update_insignificant = false;
                }
                // if post needs update, update it and mark all user entries
                // linking to this post as updated
                if ($post_needs_update) {
                    if (defined('DAEMON_EXTENDED_DEBUG')) {
                        _debug("update_rss_feed: post {$entry_guid} needs update...");
                    }
                    //						print "<!-- post $orig_title needs update : $post_needs_update -->";
                    db_query($link, "UPDATE ttrss_entries\n\t\t\t\t\t\t\tSET title = '{$entry_title}', content = '{$entry_content}',\n\t\t\t\t\t\t\t\tcontent_hash = '{$content_hash}',\n\t\t\t\t\t\t\t\tupdated = '{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t\tnum_comments = '{$num_comments}',\n\t\t\t\t\t\t\t\tplugin_data = '{$entry_plugin_data}'\n\t\t\t\t\t\t\tWHERE id = '{$ref_id}'");
                    if (!$update_insignificant) {
                        if ($mark_unread_on_update) {
                            db_query($link, "UPDATE ttrss_user_entries\n\t\t\t\t\t\t\t\t\tSET last_read = null, unread = true WHERE ref_id = '{$ref_id}'");
                        }
                    }
                }
            }
            db_query($link, "COMMIT");
            if ($debug_enabled) {
                _debug("update_rss_feed: assigning labels...");
            }
            assign_article_to_label_filters($link, $entry_ref_id, $article_filters, $owner_uid, $article_labels);
            if ($debug_enabled) {
                _debug("update_rss_feed: looking for enclosures...");
            }
            // enclosures
            $enclosures = array();
            $encs = $item->get_enclosures();
            if (is_array($encs)) {
                foreach ($encs as $e) {
                    $e_item = array($e->link, $e->type, $e->length);
                    array_push($enclosures, $e_item);
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: article enclosures:");
                print_r($enclosures);
            }
            db_query($link, "BEGIN");
            foreach ($enclosures as $enc) {
                $enc_url = db_escape_string($enc[0]);
                $enc_type = db_escape_string($enc[1]);
                $enc_dur = db_escape_string($enc[2]);
                $result = db_query($link, "SELECT id FROM ttrss_enclosures\n\t\t\t\t\t\tWHERE content_url = '{$enc_url}' AND post_id = '{$entry_ref_id}'");
                if (db_num_rows($result) == 0) {
                    db_query($link, "INSERT INTO ttrss_enclosures\n\t\t\t\t\t\t\t(content_url, content_type, title, duration, post_id) VALUES\n\t\t\t\t\t\t\t('{$enc_url}', '{$enc_type}', '', '{$enc_dur}', '{$entry_ref_id}')");
                }
            }
            db_query($link, "COMMIT");
            // check for manual tags (we have to do it here since they're loaded from filters)
            foreach ($article_filters as $f) {
                if ($f["type"] == "tag") {
                    $manual_tags = trim_array(explode(",", $f["param"]));
                    foreach ($manual_tags as $tag) {
                        if (tag_is_valid($tag)) {
                            array_push($entry_tags, $tag);
                        }
                    }
                }
            }
            // Skip boring tags
            $boring_tags = trim_array(explode(",", mb_strtolower(get_pref($link, 'BLACKLISTED_TAGS', $owner_uid, ''), 'utf-8')));
            $filtered_tags = array();
            $tags_to_cache = array();
            if ($entry_tags && is_array($entry_tags)) {
                foreach ($entry_tags as $tag) {
                    if (array_search($tag, $boring_tags) === false) {
                        array_push($filtered_tags, $tag);
                    }
                }
            }
            $filtered_tags = array_unique($filtered_tags);
            if ($debug_enabled) {
                _debug("update_rss_feed: filtered article tags:");
                print_r($filtered_tags);
            }
            // Save article tags in the database
            if (count($filtered_tags) > 0) {
                db_query($link, "BEGIN");
                foreach ($filtered_tags as $tag) {
                    $tag = sanitize_tag($tag);
                    $tag = db_escape_string($tag);
                    if (!tag_is_valid($tag)) {
                        continue;
                    }
                    $result = db_query($link, "SELECT id FROM ttrss_tags\n\t\t\t\t\t\t\tWHERE tag_name = '{$tag}' AND post_int_id = '{$entry_int_id}' AND\n\t\t\t\t\t\t\towner_uid = '{$owner_uid}' LIMIT 1");
                    if ($result && db_num_rows($result) == 0) {
                        db_query($link, "INSERT INTO ttrss_tags\n\t\t\t\t\t\t\t\t\t(owner_uid,tag_name,post_int_id)\n\t\t\t\t\t\t\t\t\tVALUES ('{$owner_uid}','{$tag}', '{$entry_int_id}')");
                    }
                    array_push($tags_to_cache, $tag);
                }
                /* update the cache */
                $tags_to_cache = array_unique($tags_to_cache);
                $tags_str = db_escape_string(join(",", $tags_to_cache));
                db_query($link, "UPDATE ttrss_user_entries\n\t\t\t\t\t\tSET tag_cache = '{$tags_str}' WHERE ref_id = '{$entry_ref_id}'\n\t\t\t\t\t\tAND owner_uid = {$owner_uid}");
                db_query($link, "COMMIT");
            }
            if (get_pref($link, "AUTO_ASSIGN_LABELS", $owner_uid, false)) {
                if ($debug_enabled) {
                    _debug("update_rss_feed: auto-assigning labels...");
                }
                foreach ($labels as $label) {
                    $caption = $label["caption"];
                    if (preg_match("/\\b{$caption}\\b/i", "{$tags_str} " . strip_tags($entry_content) . " {$entry_title}")) {
                        if (!labels_contains_caption($article_labels, $caption)) {
                            label_add_article($link, $entry_ref_id, $caption, $owner_uid);
                        }
                    }
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: article processed");
            }
        }
        if (!$last_updated) {
            if ($debug_enabled) {
                _debug("update_rss_feed: new feed, catching it up...");
            }
            catchup_feed($link, $feed, false, $owner_uid);
        }
        if ($debug_enabled) {
            _debug("purging feed...");
        }
        purge_feed($link, $feed, 0, $debug_enabled);
        db_query($link, "UPDATE ttrss_feeds\n\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
        //			db_query($link, "COMMIT");
    } else {
        $error_msg = db_escape_string(mb_substr($rss->error(), 0, 245));
        if ($debug_enabled) {
            _debug("update_rss_feed: error fetching feed: {$error_msg}");
        }
        db_query($link, "UPDATE ttrss_feeds SET last_error = '{$error_msg}',\n\t\t\t\t\tlast_updated = NOW() WHERE id = '{$feed}'");
    }
    unset($rss);
    if ($debug_enabled) {
        _debug("update_rss_feed: done");
    }
}
Beispiel #5
0
 function index()
 {
     if (!function_exists('curl_init')) {
         print "<div style='padding : 1em'>";
         print_error("This functionality requires CURL functions. Please enable CURL in your PHP configuration (you might also want to disable open_basedir in php.ini) and reload this page.");
         print "</div>";
     }
     print "<div id=\"pref-instance-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
     print "<div id=\"pref-instance-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
     print "<div id=\"pref-instance-toolbar\" dojoType=\"dijit.Toolbar\">";
     $sort = db_escape_string($_REQUEST["sort"]);
     if (!$sort || $sort == "undefined") {
         $sort = "access_url";
     }
     print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Select') . "</span>";
     print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
     print "<div onclick=\"selectTableRows('prefInstanceList', 'all')\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('All') . "</div>";
     print "<div onclick=\"selectTableRows('prefInstanceList', 'none')\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('None') . "</div>";
     print "</div></div>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"addInstance()\">" . __('Link instance') . "</button>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"editSelectedInstance()\">" . __('Edit') . "</button>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedInstances()\">" . __('Remove') . "</button>";
     print "</div>";
     #toolbar
     $result = db_query($this->link, "SELECT *,\n\t\t\t(SELECT COUNT(*) FROM ttrss_linked_feeds\n\t\t\t\tWHERE instance_id = ttrss_linked_instances.id) AS num_feeds\n\t\t\tFROM ttrss_linked_instances\n\t\t\tORDER BY {$sort}");
     print "<p class=\"insensitive\" style='margin-left : 1em;'>" . __("You can connect other instances of Tiny Tiny RSS to this one to share Popular feeds. Link to this instance of Tiny Tiny RSS by using this URL:");
     print " <a href=\"#\" onclick=\"alert('" . htmlspecialchars(get_self_url_prefix()) . "')\">(display url)</a>";
     print "<p><table width='100%' id='prefInstanceList' class='prefInstanceList' cellspacing='0'>";
     print "<tr class=\"title\">\n\t\t\t<td align='center' width=\"5%\">&nbsp;</td>\n\t\t\t<td width=''><a href=\"#\" onclick=\"updateInstanceList('access_url')\">" . __('Instance URL') . "</a></td>\n\t\t\t<td width='20%'><a href=\"#\" onclick=\"updateInstanceList('access_key')\">" . __('Access key') . "</a></td>\n\t\t\t<td width='10%'><a href=\"#\" onclick=\"updateUsersList('last_connected')\">" . __('Last connected') . "</a></td>\n\t\t\t<td width='10%'><a href=\"#\" onclick=\"updateUsersList('last_status_out')\">" . __('Status') . "</a></td>\n\t\t\t<td width='10%'><a href=\"#\" onclick=\"updateUsersList('num_feeds')\">" . __('Stored feeds') . "</a></td>\n\t\t\t</tr>";
     $lnum = 0;
     while ($line = db_fetch_assoc($result)) {
         $class = $lnum % 2 ? "even" : "odd";
         $id = $line['id'];
         $this_row_id = "id=\"LIRR-{$id}\"";
         $line["last_connected"] = make_local_datetime($this->link, $line["last_connected"], false);
         print "<tr class=\"{$class}\" {$this_row_id}>";
         print "<td align='center'><input onclick='toggleSelectRow(this);'\n\t\t\t\ttype=\"checkbox\" id=\"LICHK-{$id}\"></td>";
         $onclick = "onclick='editInstance({$id}, event)' title='" . __('Click to edit') . "'";
         $access_key = mb_substr($line['access_key'], 0, 4) . '...' . mb_substr($line['access_key'], -4);
         print "<td {$onclick}>" . htmlspecialchars($line['access_url']) . "</td>";
         print "<td {$onclick}>" . htmlspecialchars($access_key) . "</td>";
         print "<td {$onclick}>" . htmlspecialchars($line['last_connected']) . "</td>";
         print "<td {$onclick}>" . $this->status_codes[$line['last_status_out']] . "</td>";
         print "<td {$onclick}>" . htmlspecialchars($line['num_feeds']) . "</td>";
         print "</tr>";
         ++$lnum;
     }
     print "</table>";
     print "</div>";
     #pane
     print "</div>";
     #container
 }
Beispiel #6
0
 private function format_headline_subtoolbar($feed_site_url, $feed_title, $feed_id, $is_cat, $search, $match_on, $search_mode, $view_mode, $error)
 {
     $page_prev_link = "viewFeedGoPage(-1)";
     $page_next_link = "viewFeedGoPage(1)";
     $page_first_link = "viewFeedGoPage(0)";
     $catchup_page_link = "catchupPage()";
     $catchup_feed_link = "catchupCurrentFeed()";
     $catchup_sel_link = "catchupSelection()";
     $archive_sel_link = "archiveSelection()";
     $delete_sel_link = "deleteSelection()";
     $sel_all_link = "selectArticles('all')";
     $sel_unread_link = "selectArticles('unread')";
     $sel_none_link = "selectArticles('none')";
     $sel_inv_link = "selectArticles('invert')";
     $tog_unread_link = "selectionToggleUnread()";
     $tog_marked_link = "selectionToggleMarked()";
     $tog_published_link = "selectionTogglePublished()";
     if ($is_cat) {
         $cat_q = "&is_cat={$is_cat}";
     }
     if ($search) {
         $search_q = "&q={$search}&m={$match_on}&smode={$search_mode}";
     } else {
         $search_q = "";
     }
     $rss_link = htmlspecialchars(get_self_url_prefix() . "/public.php?op=rss&id={$feed_id}{$cat_q}{$search_q}");
     // right part
     $reply .= "<span class='r'>";
     if ($feed_site_url) {
         $target = "target=\"_blank\"";
         $reply .= "<a title=\"" . __("Visit the website") . "\" {$target} href=\"{$feed_site_url}\">" . truncate_string($feed_title, 30) . "</a>";
         if ($error) {
             $reply .= " (<span class=\"error\" title=\"{$error}\">Error</span>)";
         }
     } else {
         $reply .= $feed_title;
     }
     $reply .= "\r\n\t\t\t<a href=\"#\"\r\n\t\t\t\ttitle=\"" . __("View as RSS feed") . "\"\r\n\t\t\t\tonclick=\"displayDlg('generatedFeed', '{$feed_id}:{$is_cat}:{$rss_link}')\">\r\n\t\t\t\t<img class=\"noborder\" style=\"vertical-align : middle\" src=\"images/feed-icon-12x12.png\"></a>";
     $reply .= "</span>";
     // left part
     $reply .= __('Select:') . "\r\n\t\t\t<a href=\"#\" onclick=\"{$sel_all_link}\">" . __('All') . "</a>,\r\n\t\t\t<a href=\"#\" onclick=\"{$sel_unread_link}\">" . __('Unread') . "</a>,\r\n\t\t\t<a href=\"#\" onclick=\"{$sel_inv_link}\">" . __('Invert') . "</a>,\r\n\t\t\t<a href=\"#\" onclick=\"{$sel_none_link}\">" . __('None') . "</a></li>";
     $reply .= " ";
     $reply .= "<select dojoType=\"dijit.form.Select\"\r\n\t\t\tonchange=\"headlineActionsChange(this)\">";
     $reply .= "<option value=\"false\">" . __('Actions...') . "</option>";
     $reply .= "<option value=\"0\" disabled=\"1\">" . __('Selection toggle:') . "</option>";
     $reply .= "<option value=\"{$tog_unread_link}\">" . __('Unread') . "</option>\r\n\t\t\t<option value=\"{$tog_marked_link}\">" . __('Starred') . "</option>\r\n\t\t\t<option value=\"{$tog_published_link}\">" . __('Published') . "</option>";
     $reply .= "<option value=\"0\" disabled=\"1\">" . __('Selection:') . "</option>";
     $reply .= "<option value=\"{$catchup_sel_link}\">" . __('Mark as read') . "</option>";
     if ($feed_id != "0") {
         $reply .= "<option value=\"{$archive_sel_link}\">" . __('Archive') . "</option>";
     } else {
         $reply .= "<option value=\"{$archive_sel_link}\">" . __('Move back') . "</option>";
         $reply .= "<option value=\"{$delete_sel_link}\">" . __('Delete') . "</option>";
     }
     $reply .= "<option value=\"emailArticle(false)\">" . __('Forward by email') . "</option>";
     $reply .= "<option value=\"0\" disabled=\"1\">" . __('Feed:') . "</option>";
     $reply .= "<option value=\"catchupPage()\">" . __('Mark as read') . "</option>";
     $reply .= "<option value=\"displayDlg('generatedFeed', '{$feed_id}:{$is_cat}:{$rss_link}')\">" . __('View as RSS') . "</option>";
     $reply .= "</select>";
     //$reply .= "</div>";
     //$reply .= "</h2";
     return $reply;
 }
Beispiel #7
0
function twitter_dialog($link, $text)
{
    if (mb_strlen($text, 'utf-8') > 140) {
        $key = create_snippet($link, $text);
        $shorturl = new ShortUrl();
        $snippet_url = $shorturl->create(get_self_url_prefix() . '/snippet.php?key=' . $key, 'isgd');
        $tweet = truncate_string($text, 90) . " {$snippet_url}";
    } else {
        $tweet = $text;
    }
    $counter = 140 - mb_strlen($tweet, 'utf-8');
    ?>
		<div id="infoBoxTitle"><?php 
    echo __("Send Tweet");
    ?>
</div>
		<div class="infoBoxContents">
			<div id="mini-notice" style='display : none'>&nbsp;</div>
	
			<form id="new_tweet_form" onsubmit="return false;">
	
			<input type="hidden" name="op" value="send-tweet"/>

			<div class="dlgSec"><?php 
    echo __("Your tweet:");
    ?>
</div>

			<textarea onkeyup="tweet_update_counter(this)" name="text" class="tweet-text"><?php 
    echo $tweet;
    ?>
</textarea><p>

			<?php 
    if ($snippet_url) {
        ?>

			<div class="dlgSec"><?php 
        echo __("Full IRC snippet:");
        ?>
</div>
			<textarea disabled="1" class="tweet-snippet"><?php 
        echo $text;
        ?>
</textarea><p>

			<?php 
    }
    ?>

			<div class="dlgButtons">
				<div style='float : left'>
					<input id="tweet-dlg-counter" disabled="1" name="counter" value="<?php 
    echo $counter;
    ?>
">
				</div>
				<button type="submit" onclick="tweet_selection_do()"><?php 
    echo __('Tweet this!');
    ?>
</button>
				<button type="submit" onclick="close_infobox()"><?php 
    echo __('Cancel');
    ?>
</button></div>
			</div>
	
			</form>
	
		</div>
	
		<?php 
}
Beispiel #8
0
 function index()
 {
     print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
     print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Feeds') . "\">";
     $result = db_query($this->link, "SELECT COUNT(id) AS num_errors\n\t\t\tFROM ttrss_feeds WHERE last_error != '' AND owner_uid = " . $_SESSION["uid"]);
     $num_errors = db_fetch_result($result, 0, "num_errors");
     if ($num_errors > 0) {
         $error_button = "<button dojoType=\"dijit.form.Button\"\n\t\t\t  \t\tonclick=\"showFeedsWithErrors()\" id=\"errorButton\">" . __("Feeds with errors") . "</button>";
     }
     if (DB_TYPE == "pgsql") {
         $interval_qpart = "NOW() - INTERVAL '3 months'";
     } else {
         $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
     }
     $result = db_query($this->link, "SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE\n\t\t\t\t\t(SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE\n\t\t\t\t\t\tttrss_entries.id = ref_id AND\n\t\t\t\t\t\t\tttrss_user_entries.feed_id = ttrss_feeds.id) < {$interval_qpart} AND\n\t\t\tttrss_feeds.owner_uid = " . $_SESSION["uid"]);
     $num_inactive = db_fetch_result($result, 0, "num_inactive");
     if ($num_inactive > 0) {
         $inactive_button = "<button dojoType=\"dijit.form.Button\"\n\t\t\t  \t\tonclick=\"showInactiveFeeds()\">" . __("Inactive feeds") . "</button>";
     }
     $feed_search = db_escape_string($_REQUEST["search"]);
     if (array_key_exists("search", $_REQUEST)) {
         $_SESSION["prefs_feed_search"] = $feed_search;
     } else {
         $feed_search = $_SESSION["prefs_feed_search"];
     }
     print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
     print "<div region='top' dojoType=\"dijit.Toolbar\">";
     #toolbar
     print "<div style='float : right; padding-right : 4px;'>\n\t\t\t<input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"\n\t\t\t\tvalue=\"{$feed_search}\">\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">" . __('Search') . "</button>\n\t\t\t</div>";
     print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Select') . "</span>";
     print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
     print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('All') . "</div>";
     print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('None') . "</div>";
     print "</div></div>";
     print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Feeds') . "</span>";
     print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
     print "<div onclick=\"quickAddFeed()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Subscribe to feed') . "</div>";
     print "<div onclick=\"editSelectedFeed()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Edit selected feeds') . "</div>";
     print "<div onclick=\"resetFeedOrder()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Reset sort order') . "</div>";
     print "<div onclick=\"batchSubscribe()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Batch subscribe') . "</div>";
     print "</div></div>";
     if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
         print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Categories') . "</span>";
         print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
         print "<div onclick=\"editFeedCats()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('Edit categories') . "</div>";
         print "<div onclick=\"toggleHiddenFeedCats()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('(Un)hide empty categories') . "</div>";
         print "<div onclick=\"resetCatOrder()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('Reset sort order') . "</div>";
         print "</div></div>";
     }
     print $error_button;
     print $inactive_button;
     print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedFeeds()\">" . __('Unsubscribe') . "</button dojoType=\"dijit.form.Button\"> ";
     if (defined('_ENABLE_FEED_DEBUGGING')) {
         print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">\n\t\t\t\t<option value=\"facDefault\" selected>" . __('More actions...') . "</option>";
         if (FORCE_ARTICLE_PURGE == 0) {
             print "<option value=\"facPurge\">" . __('Manual purge') . "</option>";
         }
         print "\n\t\t\t\t<option value=\"facClear\">" . __('Clear feed data') . "</option>\n\t\t\t\t<option value=\"facRescore\">" . __('Rescore articles') . "</option>";
         print "</select>";
     }
     print "</div>";
     # toolbar
     //print '</div>';
     print '<div dojoType="dijit.layout.ContentPane" region="center">';
     print "<div id=\"feedlistLoading\">\n\t\t<img src='images/indicator_tiny.gif'>" . __("Loading, please wait...") . "</div>";
     print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"\n\t\t\turl=\"backend.php?op=pref-feeds&method=getfeedtree\">\n\t\t</div>\n\t\t<div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"\n\t\tquery=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"\n\t\t\tchildrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">\n\t\t</div>\n\t\t<div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"\n\t\t\tdndController=\"dijit.tree.dndSource\"\n\t\t\tbetweenThreshold=\"5\"\n\t\t\tmodel=\"feedModel\" openOnClick=\"false\">\n\t\t<script type=\"dojo/method\" event=\"onClick\" args=\"item\">\n\t\t\tvar id = String(item.id);\n\t\t\tvar bare_id = id.substr(id.indexOf(':')+1);\n\n\t\t\tif (id.match('FEED:')) {\n\t\t\t\teditFeed(bare_id);\n\t\t\t} else if (id.match('CAT:')) {\n\t\t\t\teditCat(bare_id, item);\n\t\t\t}\n\t\t</script>\n\t\t<script type=\"dojo/method\" event=\"onLoad\" args=\"item\">\n\t\t\tElement.hide(\"feedlistLoading\");\n\t\t</script>\n\t\t</div>";
     print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">\n\t\t\t" . __('<b>Hint:</b> you can drag feeds and categories around.') . "\n\t\t\t</div>";
     print '</div>';
     print '</div>';
     print "</div>";
     # feeds pane
     print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Import and export') . "\">";
     print "<h3>" . __("OPML") . "</h3>";
     print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . " ";
     print __("Only main settings profile can be migrated using OPML.") . "</p>";
     print "<iframe id=\"upload_iframe\"\n\t\t\tname=\"upload_iframe\" onload=\"opmlImportComplete(this)\"\n\t\t\tstyle=\"width: 400px; height: 100px; display: none;\"></iframe>";
     print "<form  name=\"opml_form\" style='display : block' target=\"upload_iframe\"\n\t\t\tenctype=\"multipart/form-data\" method=\"POST\"\n\t\t\taction=\"backend.php\">\n\t\t\t<input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;\n\t\t\t<input type=\"hidden\" name=\"op\" value=\"dlg\">\n\t\t\t<input type=\"hidden\" name=\"method\" value=\"importOpml\">\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" . __('Import my OPML') . "</button>";
     print "<hr>";
     print "<p>" . __('Filename:') . " <input type=\"text\" id=\"filename\" value=\"TinyTinyRSS.opml\" />&nbsp;" . __('Include settings') . "<input type=\"checkbox\" id=\"settings\" checked=\"1\"/>";
     print "</p><button dojoType=\"dijit.form.Button\"\n\t\t\tonclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" . __('Export OPML') . "</button></p></form>";
     print "<hr>";
     print "<p>" . __('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . " ";
     print __("Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.") . "</p>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('pubOPMLUrl')\">" . __('Display published OPML URL') . "</button> ";
     print "<h3>" . __("Article archive") . "</h3>";
     print "<p>" . __("You can export and import your Starred and Archived articles for safekeeping or when migrating between tt-rss instances.") . "</p>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return exportData()\">" . __('Export my data') . "</button> ";
     print "<hr>";
     print "<iframe id=\"data_upload_iframe\"\n\t\t\tname=\"data_upload_iframe\" onload=\"dataImportComplete(this)\"\n\t\t\tstyle=\"width: 400px; height: 100px; display: none;\"></iframe>";
     print "<form name=\"import_form\" style='display : block' target=\"data_upload_iframe\"\n\t\t\tenctype=\"multipart/form-data\" method=\"POST\"\n\t\t\taction=\"backend.php\">\n\t\t\t<input id=\"export_file\" name=\"export_file\" type=\"file\">&nbsp;\n\t\t\t<input type=\"hidden\" name=\"op\" value=\"dlg\">\n\t\t\t<input type=\"hidden\" name=\"method\" value=\"dataimport\">\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return importData();\" type=\"submit\">" . __('Import') . "</button>";
     print "</div>";
     # pane
     if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
         print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Firefox integration') . "\">";
         print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>";
         print "<p>";
         print "<button onclick='window.navigator.registerContentHandler(" . "\"application/vnd.mozilla.maybe.feed\", " . "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" . __('Click here to register this site as a feed reader.') . "</button>";
         print "</p>";
         print "</div>";
         # pane
     }
     print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Subscribing using bookmarklet') . "\">";
     print "<p>" . __("Drag the link below to your browser toolbar, open the feed you're interested in in your browser and click on the link to subscribe to it.") . "</p>";
     $bm_subscribe_url = str_replace('%s', '', add_feed_url());
     $confirm_str = str_replace("'", "\\'", __('Subscribe to %s in Tiny Tiny RSS?'));
     $bm_url = htmlspecialchars("javascript:{if(confirm('{$confirm_str}'.replace('%s',window.location.href)))window.location.href='{$bm_subscribe_url}'+window.location.href}");
     print "<a href=\"{$bm_url}\" class='bookmarklet'>" . __('Subscribe in Tiny Tiny RSS') . "</a>";
     print "</div>";
     #pane
     print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Published & shared articles / Generated feeds') . "\">";
     print "<h3>" . __("Published articles and generated feeds") . "</h3>";
     print "<p>" . __('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.') . "</p>";
     $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() . "/public.php?op=rss&id=-2&view-mode=all_articles");
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('generatedFeed', '{$rss_url}')\">" . __('Display URL') . "</button> ";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">" . __('Clear all generated URLs') . "</button> ";
     print "<h3>" . __("Articles shared by URL") . "</h3>";
     print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">" . __('Unshare all articles') . "</button> ";
     print "</div>";
     #pane
     if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
         print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Twitter') . "\">";
         $result = db_query($this->link, "SELECT COUNT(*) AS cid FROM ttrss_users\n\t\t\t\tWHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND\n\t\t\t\tid = " . $_SESSION['uid']);
         $is_registered = db_fetch_result($result, 0, "cid") != 0;
         if (!$is_registered) {
             print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
         } else {
             print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
         }
         print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">" . __("Register with Twitter.com") . "</button>";
         print " ";
         print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return clearTwitterCredentials()\">" . __("Clear stored credentials") . "</button>";
         print "</div>";
         # pane
     }
     print "</div>";
     #container
 }
/**
 * Compute the Mozilla Firefox feed adding URL from server HOST and REQUEST_URI.
 *
 * @return string The Mozilla Firefox feed adding URL.
 */
function add_feed_url()
{
    //$url_path = ($_SERVER['HTTPS'] != "on" ? 'http://' :  'https://') . $_SERVER["HTTP_HOST"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
    $url_path = get_self_url_prefix() . "/public.php?op=subscribe&feed_url=%s";
    return $url_path;
}
Beispiel #10
0
 private function publishArticlesById($ids, $cmode)
 {
     $tmp_ids = array();
     foreach ($ids as $id) {
         array_push($tmp_ids, "ref_id = '{$id}'");
     }
     $ids_qpart = join(" OR ", $tmp_ids);
     if ($cmode == 0) {
         $newValuepublished = "false";
     } elseif ($cmode == 1) {
         $newValuepublished = "true";
     } else {
         $newValuepublished = "published";
     }
     $this->dbh->query("UPDATE ttrss_user_entries SET\n            published = " . $newValue . ",last_published = NOW()\n            WHERE ({$ids_qpart}) AND owner_uid = " . $_SESSION["uid"]);
     if (PUBSUBHUBBUB_HUB) {
         $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key(-2, false);
         $p = new Publisher(PUBSUBHUBBUB_HUB);
         /* $pubsub_result = */
         $p->publish_update($rss_link);
     }
 }
Beispiel #11
0
function module_popup_dialog($link)
{
    $id = $_REQUEST["id"];
    $param = db_escape_string($_REQUEST["param"]);
    print "<dlg id=\"{$id}\">";
    if ($id == "importOpml") {
        print "<div class=\"prefFeedOPMLHolder\">";
        header("Content-Type: text/html");
        # required for iframe
        $owner_uid = $_SESSION["uid"];
        db_query($link, "BEGIN");
        /* create Imported feeds category just in case */
        $result = db_query($link, "SELECT id FROM\n\t\t\t\tttrss_feed_categories WHERE title = 'Imported feeds' AND\n\t\t\t\towner_uid = '{$owner_uid}' LIMIT 1");
        if (db_num_rows($result) == 0) {
            db_query($link, "INSERT INTO ttrss_feed_categories\n\t\t\t\t\t(title,owner_uid)\n\t\t\t\t\t\tVALUES ('Imported feeds', '{$owner_uid}')");
        }
        db_query($link, "COMMIT");
        /* Handle OPML import by DOMXML/DOMDocument */
        if (function_exists('domxml_open_file')) {
            print "<ul class='nomarks'>";
            print "<li>" . __("Importing using DOMXML.") . "</li>";
            require_once "opml_domxml.php";
            opml_import_domxml($link, $owner_uid);
            print "</ul>";
        } else {
            if (PHP_VERSION >= 5) {
                print "<ul class='nomarks'>";
                print "<li>" . __("Importing using DOMDocument.") . "</li>";
                require_once "opml_domdoc.php";
                opml_import_domdoc($link, $owner_uid);
                print "</ul>";
            } else {
                print_error(__("DOMXML extension is not found. It is required for PHP versions below 5."));
            }
        }
        print "</div>";
        print "<div align='center'>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('opmlImportDlg').hide()\">" . __('Close this window') . "</button>";
        print "</div>";
        print "</div>";
        //return;
    }
    if ($id == "editPrefProfiles") {
        print "<div dojoType=\"dijit.Toolbar\">";
        #			TODO: depends on selectTableRows() being broken for this list
        #			print "<div dojoType=\"dijit.form.DropDownButton\">".
        #				"<span>" . __('Select')."</span>";
        #			print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
        #			print "<div onclick=\"selectTableRows('prefFeedProfileList', 'all')\"
        #				dojoType=\"dijit.MenuItem\">".__('All')."</div>";
        #			print "<div onclick=\"selectTableRows('prefFeedProfileList', 'none')\"
        #				dojoType=\"dijit.MenuItem\">".__('None')."</div>";
        #			print "</div></div>";
        #			print "<div style='float : right'>";
        print "<input name=\"newprofile\" dojoType=\"dijit.form.ValidationTextBox\"\n\t\t\t\t\trequired=\"1\">\n\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('profileEditDlg').addProfile()\">" . __('Create profile') . "</button></div>";
        #			print "</div>";
        $result = db_query($link, "SELECT title,id FROM ttrss_settings_profiles\n\t\t\t\tWHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY title");
        print "<div class=\"prefFeedCatHolder\">";
        print "<form id=\"profile_edit_form\" onsubmit=\"return false\">";
        print "<table width=\"100%\" class=\"prefFeedProfileList\"\n\t\t\t\tcellspacing=\"0\" id=\"prefFeedProfileList\">";
        print "<tr class=\"\" id=\"FCATR-0\">";
        #odd
        print "<td width='5%' align='center'><input\n\t\t\t\tonclick='toggleSelectRow2(this);'\n\t\t\t\tdojoType=\"dijit.form.CheckBox\"\n\t\t\t\ttype=\"checkbox\"></td>";
        if (!$_SESSION["profile"]) {
            $is_active = __("(active)");
        } else {
            $is_active = "";
        }
        print "<td><span>" . __("Default profile") . " {$is_active}</span></td>";
        print "</tr>";
        $lnum = 1;
        while ($line = db_fetch_assoc($result)) {
            $class = $lnum % 2 ? "even" : "odd";
            $profile_id = $line["id"];
            $this_row_id = "id=\"FCATR-{$profile_id}\"";
            print "<tr class=\"\" {$this_row_id}>";
            $edit_title = htmlspecialchars($line["title"]);
            print "<td width='5%' align='center'><input\n\t\t\t\t\tonclick='toggleSelectRow2(this);'\n\t\t\t\t\tdojoType=\"dijit.form.CheckBox\"\n\t\t\t\t\ttype=\"checkbox\"></td>";
            if ($_SESSION["profile"] == $line["id"]) {
                $is_active = __("(active)");
            } else {
                $is_active = "";
            }
            print "<td><span dojoType=\"dijit.InlineEditBox\"\n\t\t\t\t\twidth=\"300px\" autoSave=\"false\"\n\t\t\t\t\tprofile-id=\"{$profile_id}\">" . $edit_title . "<script type=\"dojo/method\" event=\"onChange\" args=\"item\">\n\t\t\t\t\t\tvar elem = this;\n\t\t\t\t\t\tdojo.xhrPost({\n\t\t\t\t\t\t\turl: 'backend.php',\n\t\t\t\t\t\t\tcontent: {op: 'rpc', subop: 'saveprofile',\n\t\t\t\t\t\t\t\tvalue: this.value,\n\t\t\t\t\t\t\t\tid: this.srcNodeRef.getAttribute('profile-id')},\n\t\t\t\t\t\t\t\tload: function(response) {\n\t\t\t\t\t\t\t\t\telem.attr('value', response);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t</script>\n\t\t\t\t</span> {$is_active}</td>";
            print "</tr>";
            ++$lnum;
        }
        print "</table>";
        print "</form>";
        print "</div>";
        print "<div class='dlgButtons'>\n\t\t\t\t<div style='float : left'>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').removeSelected()\">" . __('Remove selected profiles') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').activateProfile()\">" . __('Activate profile') . "</button>\n\t\t\t\t</div>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').hide()\">" . __('Close this window') . "</button>";
        print "</div>";
    }
    if ($id == "pubOPMLUrl") {
        print "<title>" . __('Public OPML URL') . "</title>";
        print "<content><![CDATA[";
        $url_path = opml_publish_url($link);
        print __("Your Public OPML URL is:");
        print "<div class=\"tagCloudContainer\">";
        print "<a id='pub_opml_url' href='{$url_path}' target='_blank'>{$url_path}</a>";
        print "</div>";
        print "<div align='center'>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return opmlRegenKey()\">" . __('Generate new URL') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return closeInfoBox()\">" . __('Close this window') . "</button>";
        print "</div>";
        print "]]></content>";
        //return;
    }
    if ($id == "explainError") {
        print "<title>" . __('Notice') . "</title>";
        print "<content><![CDATA[";
        print "<div class=\"errorExplained\">";
        if ($param == 1) {
            print __("Update daemon is enabled in configuration, but daemon process is not running, which prevents all feeds from updating. Please start the daemon process or contact instance owner.");
            $stamp = (int) file_get_contents(LOCK_DIRECTORY . "/update_daemon.stamp");
            print "<p>" . __("Last update:") . " " . date("Y.m.d, G:i", $stamp);
        }
        if ($param == 3) {
            print __("Update daemon is taking too long to perform a feed update. This could indicate a problem like crash or a hang. Please check the daemon process or contact instance owner.");
            $stamp = (int) file_get_contents(LOCK_DIRECTORY . "/update_daemon.stamp");
            print "<p>" . __("Last update:") . " " . date("Y.m.d, G:i", $stamp);
        }
        print "</div>";
        print "<div align='center'>";
        print "<button onclick=\"return closeInfoBox()\">" . __('Close this window') . "</button>";
        print "</div>";
        print "]]></content>";
        //return;
    }
    if ($id == "quickAddFeed") {
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"addfeed\">";
        print "<div class=\"dlgSec\">" . __("Feed") . "</div>";
        print "<div class=\"dlgSecCont\">";
        print "<input style=\"font-size : 16px; width : 20em;\"\n\t\t\t\tplaceHolder=\"" . __("Feed URL") . "\"\n\t\t\t\tdojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"feed\" id=\"feedDlg_feedUrl\">";
        print "<hr/>";
        if (get_pref($link, 'ENABLE_FEED_CATS')) {
            print __('Place in category:') . " ";
            print_feed_cat_select($link, "cat", false, 'dojoType="dijit.form.Select"');
        }
        print "</div>";
        print '<div id="feedDlg_feedsContainer" style="display : none">

					<div class="dlgSec">' . __('Available feeds') . '</div>
					<div class="dlgSecCont">' . '<select id="feedDlg_feedContainerSelect"
						dojoType="dijit.form.Select" size="3">
						<script type="dojo/method" event="onChange" args="value">
							dijit.byId("feedDlg_feedUrl").attr("value", value);
						</script>
					</select>' . '</div></div>';
        print "<div id='feedDlg_loginContainer' style='display : none'>\n\n\t\t\t\t\t<div class=\"dlgSec\">" . __("Authentication") . "</div>\n\t\t\t\t\t<div class=\"dlgSecCont\">" . " <input dojoType=\"dijit.form.TextBox\" name='login'\"\n\t\t\t\t\t\tplaceHolder=\"" . __("Login") . "\"\n\t\t\t\t\t\tstyle=\"width : 10em;\"> " . " <input\n\t\t\t\t\t\tplaceHolder=\"" . __("Password") . "\"\n\t\t\t\t\t\tdojoType=\"dijit.form.TextBox\" type='password'\n\t\t\t\t\t\tstyle=\"width : 10em;\" name='pass'\">\n\t\t\t\t</div></div>";
        print "<div style=\"clear : both\">\n\t\t\t\t<input type=\"checkbox\" dojoType=\"dijit.form.CheckBox\" id=\"feedDlg_loginCheck\"\n\t\t\t\t\t\tonclick='checkboxToggleElement(this, \"feedDlg_loginContainer\")'>\n\t\t\t\t\t<label for=\"feedDlg_loginCheck\">" . __('This feed requires authentication.') . "</div>";
        print "</form>";
        print "<div class=\"dlgButtons\">\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedAddDlg').execute()\">" . __('Subscribe') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return feedBrowser()\">" . __('More feeds') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedAddDlg').hide()\">" . __('Cancel') . "</button>\n\t\t\t\t</div>";
        //return;
    }
    if ($id == "feedBrowser") {
        $browser_search = db_escape_string($_REQUEST["search"]);
        #			print "<form onsubmit='return false;' display='inline'
        #				name='feed_browser' id='feed_browser'>";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"updateFeedBrowser\">";
        print "<div dojoType=\"dijit.Toolbar\">\n\t\t\t\t<div style='float : right'>\n\t\t\t\t<img style='display : none'\n\t\t\t\t\tid='feed_browser_spinner' src='" . theme_image($link, 'images/indicator_white.gif') . "'>\n\t\t\t\t<input name=\"search\" dojoType=\"dijit.form.TextBox\" size=\"20\" type=\"search\"\n\t\t\t\t\tonchange=\"dijit.byId('feedBrowserDlg').update()\" value=\"{$browser_search}\">\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').update()\">" . __('Search') . "</button>\n\t\t\t</div>";
        print " <select name=\"mode\" dojoType=\"dijit.form.Select\" onchange=\"dijit.byId('feedBrowserDlg').update()\">\n\t\t\t\t<option value='1'>" . __('Popular feeds') . "</option>\n\t\t\t\t<option value='2'>" . __('Feed archive') . "</option>\n\t\t\t\t</select> ";
        print __("limit:");
        print " <select dojoType=\"dijit.form.Select\" name=\"limit\" onchange=\"dijit.byId('feedBrowserDlg').update()\">";
        foreach (array(25, 50, 100, 200) as $l) {
            $issel = $l == $limit ? "selected=\"1\"" : "";
            print "<option {$issel} value=\"{$l}\">{$l}</option>";
        }
        print "</select> ";
        print "</div>";
        $owner_uid = $_SESSION["uid"];
        print "<ul class='browseFeedList' id='browseFeedList'>";
        print make_feed_browser($link, $search, 25);
        print "</ul>";
        print "<div align='center'>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').execute()\">" . __('Subscribe') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" style='display : none' id='feed_archive_remove' onclick=\"dijit.byId('feedBrowserDlg').removeFromArchive()\">" . __('Remove') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').hide()\" >" . __('Cancel') . "</button></div>";
    }
    if ($id == "search") {
        $params = explode(":", db_escape_string($_REQUEST["param"]), 2);
        $active_feed_id = sprintf("%d", $params[0]);
        $is_cat = $params[1] != "false";
        print "<div class=\"dlgSec\">" . __('Look for') . "</div>";
        print "<div class=\"dlgSecCont\">";
        if (!SPHINX_ENABLED) {
            print "<input dojoType=\"dijit.form.ValidationTextBox\"\n\t\t\t\t\tstyle=\"font-size : 16px; width : 12em;\"\n\t\t\t\t\trequired=\"1\" name=\"query\" type=\"search\" value=''>";
            print " " . __('match on') . " ";
            $search_fields = array("title" => __("Title"), "content" => __("Content"), "both" => __("Title or content"));
            print_select_hash("match_on", 3, $search_fields, 'dojoType="dijit.form.Select"');
        } else {
            print "<input dojoType=\"dijit.form.ValidationTextBox\"\n\t\t\t\t\tstyle=\"font-size : 16px; width : 20em;\"\n\t\t\t\t\trequired=\"1\" name=\"query\" type=\"search\" value=''>";
        }
        print "<hr/>" . __('Limit search to:') . " ";
        print "<select name=\"search_mode\" dojoType=\"dijit.form.Select\">\n\t\t\t\t<option value=\"all_feeds\">" . __('All feeds') . "</option>";
        $feed_title = getFeedTitle($link, $active_feed_id);
        if (!$is_cat) {
            $feed_cat_title = getFeedCatTitle($link, $active_feed_id);
        } else {
            $feed_cat_title = getCategoryTitle($link, $active_feed_id);
        }
        if ($active_feed_id && !$is_cat) {
            print "<option selected=\"1\" value=\"this_feed\">{$feed_title}</option>";
        } else {
            print "<option disabled=\"1\" value=\"false\">" . __('This feed') . "</option>";
        }
        if ($is_cat) {
            $cat_preselected = "selected=\"1\"";
        }
        if (get_pref($link, 'ENABLE_FEED_CATS') && ($active_feed_id > 0 || $is_cat)) {
            print "<option {$cat_preselected} value=\"this_cat\">{$feed_cat_title}</option>";
        } else {
            //print "<option disabled>".__('This category')."</option>";
        }
        print "</select>";
        print "</div>";
        print "<div class=\"dlgButtons\">";
        if (!SPHINX_ENABLED) {
            print "<div style=\"float : left\">\n\t\t\t\t\t<a class=\"visibleLink\" target=\"_blank\" href=\"http://tt-rss.org/redmine/wiki/tt-rss/SearchSyntax\">Search syntax</a>\n\t\t\t\t\t</div>";
        }
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('searchDlg').execute()\">" . __('Search') . "</button>\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('searchDlg').hide()\">" . __('Cancel') . "</button>\n\t\t\t</div>";
    }
    if ($id == "quickAddFilter") {
        $active_feed_id = db_escape_string($_REQUEST["param"]);
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-filters\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"quiet\" value=\"1\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"add\">";
        $result = db_query($link, "SELECT id,description\n\t\t\t\tFROM ttrss_filter_types ORDER BY description");
        $filter_types = array();
        while ($line = db_fetch_assoc($result)) {
            //array_push($filter_types, $line["description"]);
            $filter_types[$line["id"]] = __($line["description"]);
        }
        print "<div class=\"dlgSec\">" . __("Match") . "</div>";
        print "<div class=\"dlgSecCont\">";
        print "<span id=\"filterDlg_dateModBox\" style=\"display : none\">";
        $filter_params = array("before" => __("before"), "after" => __("after"));
        print_select_hash("filter_date_modifier", "before", $filter_params, 'dojoType="dijit.form.Select"');
        print "&nbsp;</span>";
        print "<input dojoType=\"dijit.form.ValidationTextBox\"\n\t\t\t\t required=\"true\" id=\"filterDlg_regExp\"\n\t\t\t\t style=\"font-size : 16px\"\n\t\t\t\t name=\"reg_exp\" value=\"{$reg_exp}\"/>";
        print "<span id=\"filterDlg_dateChkBox\" style=\"display : none\">";
        print "&nbsp;<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return filterDlgCheckDate()\">" . __('Check it') . "</button>";
        print "</span>";
        print "<hr/>" . __("on field") . " ";
        print_select_hash("filter_type", 1, $filter_types, 'onchange="filterDlgCheckType(this)" dojoType="dijit.form.Select"');
        print "<hr/>";
        print __("in") . " ";
        print_feed_select($link, "feed_id", $active_feed_id, 'dojoType="dijit.form.FilteringSelect"');
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Perform Action") . "</div>";
        print "<div class=\"dlgSecCont\">";
        print "<select name=\"action_id\" dojoType=\"dijit.form.Select\"\n\t\t\t\tonchange=\"filterDlgCheckAction(this)\">";
        $result = db_query($link, "SELECT id,description FROM ttrss_filter_actions\n\t\t\t\tORDER BY name");
        while ($line = db_fetch_assoc($result)) {
            printf("<option value='%d'>%s</option>", $line["id"], __($line["description"]));
        }
        print "</select>";
        print "<span id=\"filterDlg_paramBox\" style=\"display : none\">";
        print " " . __("with parameters:") . " ";
        print "<input dojoType=\"dijit.form.TextBox\"\n\t\t\t\tid=\"filterDlg_actionParam\"\n\t\t\t\tname=\"action_param\">";
        print_label_select($link, "action_param_label", $action_param, 'id="filterDlg_actionParamLabel" dojoType="dijit.form.Select"');
        print "</span>";
        print "&nbsp;";
        // tiny layout hack
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Options") . "</div>";
        print "<div class=\"dlgSecCont\">";
        print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"enabled\" id=\"enabled\" checked=\"1\">\n\t\t\t\t\t<label for=\"enabled\">" . __('Enabled') . "</label><hr/>";
        print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"inverse\" id=\"inverse\">\n\t\t\t\t<label for=\"inverse\">" . __('Inverse match') . "</label>";
        print "</div>";
        print "<div class=\"dlgButtons\">";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').test()\">" . __('Test') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').execute()\">" . __('Create') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').hide()\">" . __('Cancel') . "</button>";
        print "</div>";
        //return;
    }
    if ($id == "inactiveFeeds") {
        if (DB_TYPE == "pgsql") {
            $interval_qpart = "NOW() - INTERVAL '3 months'";
        } else {
            $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
        }
        $result = db_query($link, "SELECT ttrss_feeds.title, ttrss_feeds.site_url,\n\t\t\t  \t\tttrss_feeds.feed_url, ttrss_feeds.id, MAX(updated) AS last_article\n\t\t\t\tFROM ttrss_feeds, ttrss_entries, ttrss_user_entries WHERE\n\t\t\t\t\t(SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE\n\t\t\t\t\t\tttrss_entries.id = ref_id AND\n\t\t\t\t\t\t\tttrss_user_entries.feed_id = ttrss_feeds.id) < {$interval_qpart}\n\t\t\t\tAND ttrss_feeds.owner_uid = " . $_SESSION["uid"] . " AND\n\t\t\t\t\tttrss_user_entries.feed_id = ttrss_feeds.id AND\n\t\t\t\t\tttrss_entries.id = ref_id\n\t\t\t\tGROUP BY ttrss_feeds.title, ttrss_feeds.id, ttrss_feeds.site_url, ttrss_feeds.feed_url\n\t\t\t\tORDER BY last_article");
        print __("These feeds have not been updated with new content for 3 months (oldest first):");
        print "<div class=\"inactiveFeedHolder\">";
        print "<table width=\"100%\" cellspacing=\"0\" id=\"prefInactiveFeedList\">";
        $lnum = 1;
        while ($line = db_fetch_assoc($result)) {
            $class = $lnum % 2 ? "even" : "odd";
            $feed_id = $line["id"];
            $this_row_id = "id=\"FUPDD-{$feed_id}\"";
            print "<tr class=\"\" {$this_row_id}>";
            $edit_title = htmlspecialchars($line["title"]);
            print "<td width='5%' align='center'><input\n\t\t\t\t\tonclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"\n\t\t\t\t\ttype=\"checkbox\"></td>";
            print "<td>";
            print "<a class=\"visibleLink\" href=\"#\" " . "title=\"" . __("Click to edit feed") . "\" " . "onclick=\"editFeed(" . $line["id"] . ")\">" . htmlspecialchars($line["title"]) . "</a>";
            print "</td><td class=\"insensitive\" align='right'>";
            print make_local_datetime($link, $line['last_article'], false);
            print "</td>";
            print "</tr>";
            ++$lnum;
        }
        print "</table>";
        print "</div>";
        print "<div class='dlgButtons'>";
        print "<div style='float : left'>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('inactiveFeedsDlg').removeSelected()\">" . __('Unsubscribe from selected feeds') . "</button> ";
        print "</div>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('inactiveFeedsDlg').hide()\">" . __('Close this window') . "</button>";
        print "</div>";
    }
    if ($id == "feedsWithErrors") {
        #			print "<title>".__('Feeds with update errors')."</title>";
        #			print "<content><![CDATA[";
        print __("These feeds have not been updated because of errors:");
        $result = db_query($link, "SELECT id,title,feed_url,last_error,site_url\n\t\t\tFROM ttrss_feeds WHERE last_error != '' AND owner_uid = " . $_SESSION["uid"]);
        print "<div class=\"inactiveFeedHolder\">";
        print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
        $lnum = 1;
        while ($line = db_fetch_assoc($result)) {
            $class = $lnum % 2 ? "even" : "odd";
            $feed_id = $line["id"];
            $this_row_id = "id=\"FUPDD-{$feed_id}\"";
            print "<tr class=\"\" {$this_row_id}>";
            $edit_title = htmlspecialchars($line["title"]);
            print "<td width='5%' align='center'><input\n\t\t\t\t\tonclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"\n\t\t\t\t\ttype=\"checkbox\"></td>";
            print "<td>";
            print "<a class=\"visibleLink\" href=\"#\" " . "title=\"" . __("Click to edit feed") . "\" " . "onclick=\"editFeed(" . $line["id"] . ")\">" . htmlspecialchars($line["title"]) . "</a>: ";
            print "<span class=\"insensitive\">";
            print htmlspecialchars($line["last_error"]);
            print "</span>";
            print "</td>";
            print "</tr>";
            ++$lnum;
        }
        print "</table>";
        print "</div>";
        print "<div class='dlgButtons'>";
        print "<div style='float : left'>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('errorFeedsDlg').removeSelected()\">" . __('Unsubscribe from selected feeds') . "</button> ";
        print "</div>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('errorFeedsDlg').hide()\">" . __('Close this window') . "</button>";
        print "</div>";
    }
    if ($id == "editArticleTags") {
        #			print "<form id=\"tag_edit_form\" onsubmit='return false'>";
        print __("Tags for this article (separated by commas):") . "<br>";
        $tags = get_article_tags($link, $param);
        $tags_str = join(", ", $tags);
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"{$param}\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"setArticleTags\">";
        print "<table width='100%'><tr><td>";
        print "<textarea dojoType=\"dijit.form.SimpleTextarea\" rows='4'\n\t\t\t\tstyle='font-size : 12px; width : 100%' id=\"tags_str\"\n\t\t\t\tname='tags_str'>{$tags_str}</textarea>\n\t\t\t<div class=\"autocomplete\" id=\"tags_choices\"\n\t\t\t\t\tstyle=\"display:none\"></div>";
        print "</td></tr></table>";
        #			print "</form>";
        print "<div class='dlgButtons'>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('editTagsDlg').execute()\">" . __('Save') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('editTagsDlg').hide()\">" . __('Cancel') . "</button>";
        print "</div>";
    }
    if ($id == "printTagCloud") {
        print "<title>" . __('Tag Cloud') . "</title>";
        print "<content><![CDATA[";
        #			print __("Showing most popular tags ")." (<a
        #			href='javascript:toggleTags(true)'>".__('more tags')."</a>):<br/>";
        print "<div class=\"tagCloudContainer\">";
        printTagCloud($link);
        print "</div>";
        print "<div align='center'>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return closeInfoBox()\">" . __('Close this window') . "</button>";
        print "</div>";
        print "]]></content>";
    }
    if ($id == 'printTagSelect') {
        print "<title>" . __('Select item(s) by tags') . "</title>";
        print "<content><![CDATA[";
        print __("Match:") . "&nbsp;" . "<input class=\"noborder\" dojoType=\"dijit.form.RadioButton\" type=\"radio\" checked value=\"any\" name=\"tag_mode\">&nbsp;Any&nbsp;";
        print "<input class=\"noborder\" dojoType=\"dijit.form.RadioButton\" type=\"radio\" value=\"all\" name=\"tag_mode\">&nbsp;All&nbsp;";
        print "&nbsp;tags.";
        print "<select id=\"all_tags\" name=\"all_tags\" title=\"" . __('Which Tags?') . "\" multiple=\"multiple\" size=\"10\" style=\"width : 100%\">";
        $result = db_query($link, "SELECT DISTINCT tag_name FROM ttrss_tags WHERE owner_uid = " . $_SESSION['uid'] . "\n\t\t\t\tAND LENGTH(tag_name) <= 30 ORDER BY tag_name ASC");
        while ($row = db_fetch_assoc($result)) {
            $tmp = htmlspecialchars($row["tag_name"]);
            print "<option value=\"" . str_replace(" ", "%20", $tmp) . "\">{$tmp}</option>";
        }
        print "</select>";
        print "<div align='right'>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"viewfeed(get_all_tags(\$('all_tags')),\n\t\t\t\tget_radio_checked(\$('tag_mode')));\">" . __('Display entries') . "</button>";
        print "&nbsp;";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\tonclick=\"return closeInfoBox()\">" . __('Close this window') . "</button>";
        print "</div>";
        print "]]></content>";
    }
    if ($id == "emailArticle") {
        $secretkey = sha1(uniqid(rand(), true));
        $_SESSION['email_secretkey'] = $secretkey;
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"secretkey\" value=\"{$secretkey}\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"sendEmail\">";
        $result = db_query($link, "SELECT email, full_name FROM ttrss_users WHERE\n\t\t\t\tid = " . $_SESSION["uid"]);
        $user_email = htmlspecialchars(db_fetch_result($result, 0, "email"));
        $user_name = htmlspecialchars(db_fetch_result($result, 0, "full_name"));
        if (!$user_name) {
            $user_name = $_SESSION['name'];
        }
        $_SESSION['email_replyto'] = $user_email;
        $_SESSION['email_fromname'] = $user_name;
        require_once "lib/MiniTemplator.class.php";
        $tpl = new MiniTemplator();
        $tpl_t = new MiniTemplator();
        $tpl->readTemplateFromFile("templates/email_article_template.txt");
        $tpl->setVariable('USER_NAME', $_SESSION["name"]);
        $tpl->setVariable('USER_EMAIL', $user_email);
        $tpl->setVariable('TTRSS_HOST', $_SERVER["HTTP_HOST"]);
        //			$tpl->addBlock('header');
        $result = db_query($link, "SELECT link, content, title\n\t\t\t\tFROM ttrss_user_entries, ttrss_entries WHERE id = ref_id AND\n\t\t\t\tid IN ({$param}) AND owner_uid = " . $_SESSION["uid"]);
        if (db_num_rows($result) > 1) {
            $subject = __("[Forwarded]") . " " . __("Multiple articles");
        }
        while ($line = db_fetch_assoc($result)) {
            if (!$subject) {
                $subject = __("[Forwarded]") . " " . htmlspecialchars($line["title"]);
            }
            $tpl->setVariable('ARTICLE_TITLE', strip_tags($line["title"]));
            $tpl->setVariable('ARTICLE_URL', strip_tags($line["link"]));
            $tpl->addBlock('article');
        }
        $tpl->addBlock('email');
        $content = "";
        $tpl->generateOutputToString($content);
        print "<table width='100%'><tr><td>";
        print __('From:');
        print "</td><td>";
        print "<input dojoType=\"dijit.form.TextBox\" disabled=\"1\" style=\"width : 30em;\"\n\t\t\t\t\tvalue=\"{$user_name} <{$user_email}>\">";
        print "</td></tr><tr><td>";
        print __('To:');
        print "</td><td>";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"true\"\n\t\t\t\t\tstyle=\"width : 30em;\"\n\t\t\t\t\tname=\"destination\" id=\"emailArticleDlg_destination\">";
        print "<div class=\"autocomplete\" id=\"emailArticleDlg_dst_choices\"\n\t\t\t\t\tstyle=\"z-index: 30; display : none\"></div>";
        print "</td></tr><tr><td>";
        print __('Subject:');
        print "</td><td>";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"true\"\n\t\t\t\t\tstyle=\"width : 30em;\"\n\t\t\t\t\tname=\"subject\" value=\"{$subject}\" id=\"subject\">";
        print "</td></tr>";
        print "<tr><td colspan='2'><textarea dojoType=\"dijit.form.SimpleTextarea\" style='font-size : 12px; width : 100%' rows=\"20\"\n\t\t\t\tname='content'>{$content}</textarea>";
        print "</td></tr></table>";
        print "<div class='dlgButtons'>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('emailArticleDlg').execute()\">" . __('Send e-mail') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('emailArticleDlg').hide()\">" . __('Cancel') . "</button>";
        print "</div>";
        //return;
    }
    if ($id == "generatedFeed") {
        print "<title>" . __('View as RSS') . "</title>";
        print "<content><![CDATA[";
        $params = explode(":", $param, 3);
        $feed_id = db_escape_string($params[0]);
        $is_cat = (bool) $params[1];
        $key = get_feed_access_key($link, $feed_id, $is_cat);
        $url_path = htmlspecialchars($params[2]) . "&key=" . $key;
        print __("You can view this feed as RSS using the following URL:");
        print "<div class=\"tagCloudContainer\">";
        print "<a id='gen_feed_url' href='{$url_path}' target='_blank'>{$url_path}</a>";
        print "</div>";
        print "<div align='center'>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return genUrlChangeKey('{$feed_id}', '{$is_cat}')\">" . __('Generate new URL') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return closeInfoBox()\">" . __('Close this window') . "</button>";
        print "</div>";
        print "]]></content>";
        //return;
    }
    if ($id == "newVersion") {
        $version_data = check_for_update($link);
        $version = $version_data['version'];
        $id = $version_data['version_id'];
        print "<div class='tagCloudContainer'>";
        print T_sprintf("New version of Tiny Tiny RSS is available (%s).", "<b>{$version}</b>");
        print "</div>";
        $details = "http://tt-rss.org/redmine/versions/show/{$id}";
        $download = "http://tt-rss.org/#Download";
        print "<div style='text-align : center'>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return window.open('{$details}')\">" . __("Details") . "</button>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return window.open('{$download}')\">" . __("Download") . "</button>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return dijit.byId('newVersionDlg').hide()\">" . __('Close this window') . "</button>";
        print "</div>";
    }
    if ($id == "customizeCSS") {
        $value = get_pref($link, "USER_STYLESHEET");
        $value = str_replace("<br/>", "\n", $value);
        print T_sprintf("You can override colors, fonts and layout of your currently selected theme with custom CSS declarations here. <a target=\"_blank\" class=\"visibleLink\" href=\"%s\">This file</a> can be used as a baseline.", "tt-rss.css");
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"setpref\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"key\" value=\"USER_STYLESHEET\">";
        print "<table width='100%'><tr><td>";
        print "<textarea dojoType=\"dijit.form.SimpleTextarea\"\n\t\t\t\tstyle='font-size : 12px; width : 100%; height: 200px;'\n\t\t\t\tplaceHolder='body#ttrssMain { font-size : 14px; };'\n\t\t\t\tname='value'>{$value}</textarea>";
        print "</td></tr></table>";
        print "<div class='dlgButtons'>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('cssEditDlg').execute()\">" . __('Save') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('cssEditDlg').hide()\">" . __('Cancel') . "</button>";
        print "</div>";
    }
    if ($id == "editArticleNote") {
        $result = db_query($link, "SELECT note FROM ttrss_user_entries WHERE\n\t\t\t\tref_id = '{$param}' AND owner_uid = " . $_SESSION['uid']);
        $note = db_fetch_result($result, 0, "note");
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"{$param}\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"setNote\">";
        print "<table width='100%'><tr><td>";
        print "<textarea dojoType=\"dijit.form.SimpleTextarea\"\n\t\t\t\tstyle='font-size : 12px; width : 100%; height: 100px;'\n\t\t\t\tplaceHolder='body#ttrssMain { font-size : 14px; };'\n\t\t\t\tname='note'>{$note}</textarea>";
        print "</td></tr></table>";
        print "<div class='dlgButtons'>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('editNoteDlg').execute()\">" . __('Save') . "</button> ";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"dijit.byId('editNoteDlg').hide()\">" . __('Cancel') . "</button>";
        print "</div>";
    }
    if ($id == "about") {
        print "<table width='100%'><tr><td align='center'>";
        print "<img src=\"images/logo_big.png\">";
        print "</td>";
        print "<td width='70%'>";
        print "<h1>Tiny Riny RSS</h1>\n\t\t\t\t<strong>Version " . VERSION . "</strong>\n\t\t\t\t<p>Copyright &copy; 2005-" . date('Y') . "\n\t\t\t\t<a target=\"_blank\" class=\"visibleLink\"\n\t\t\t\thref=\"http://fakecake.org/\">Andrew Dolgov</a>\n\t\t\t\tand other contributors.</p>\n\t\t\t\t<p class=\"insensitive\">Licensed under GNU GPL version 2.</p>";
        print "<p class=\"insensitive\">\n\t\t\t\t<a class=\"visibleLink\" target=\"_blank\"\n\t\t\t\t\thref=\"http://tt-rss.org/\">Official site</a> &mdash;\n\t\t\t\t<a href=\"http://tt-rss.org/redmine/wiki/tt-rss/Donate\"\n\t\t\t\ttarget=\"_blank\" class=\"visibleLink\">\n\t\t\t\tSupport the project.</a></p>";
        print "</td></tr>";
        print "</table>";
        print "<div align='center'>";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\ttype=\"submit\">" . __('Close this window') . "</button>";
        print "</div>";
    }
    if ($id == "addInstance") {
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\"  name=\"op\" value=\"pref-instances\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\"  name=\"subop\" value=\"add\">";
        print "<div class=\"dlgSec\">" . __("Instance") . "</div>";
        print "<div class=\"dlgSecCont\">";
        /* URL */
        print __("URL:") . " ";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"\n\t\t\t\tplaceHolder=\"" . __("Instance URL") . "\"\n\t\t\t\tregExp='^(http|https)://.*'\n\t\t\t\tstyle=\"font-size : 16px; width: 20em\" name=\"access_url\">";
        print "<hr/>";
        $access_key = sha1(uniqid(rand(), true));
        /* Access key */
        print __("Access key:") . " ";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"\n\t\t\t\tplaceHolder=\"" . __("Access key") . "\" regExp='\\w{40}'\n\t\t\t\tstyle=\"width: 20em\" name=\"access_key\" id=\"instance_add_key\"\n\t\t\t\tvalue=\"{$access_key}\">";
        print "<p class='insensitive'>" . __("Use one access key for both linked instances.");
        print "</div>";
        print "<div class=\"dlgButtons\">\n\t\t\t\t<div style='float : left'>\n\t\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\t\t\tonclick=\"return dijit.byId('instanceAddDlg').regenKey()\">" . __('Generate new key') . "</button>\n\t\t\t\t</div>\n\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\t\tonclick=\"return dijit.byId('instanceAddDlg').execute()\">" . __('Create link') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\t\tonclick=\"return dijit.byId('instanceAddDlg').hide()\"\">" . __('Cancel') . "</button></div>";
        return;
    }
    if ($id == "shareArticle") {
        $result = db_query($link, "SELECT uuid, ref_id FROM ttrss_user_entries WHERE int_id = '{$param}'\n\t\t\t\tAND owner_uid = " . $_SESSION['uid']);
        if (db_num_rows($result) == 0) {
            print "Article not found.";
        } else {
            $uuid = db_fetch_result($result, 0, "uuid");
            $ref_id = db_fetch_result($result, 0, "ref_id");
            if (!$uuid) {
                $uuid = db_escape_string(sha1(uniqid(rand(), true)));
                db_query($link, "UPDATE ttrss_user_entries SET uuid = '{$uuid}' WHERE int_id = '{$param}'\n\t\t\t\t\t\tAND owner_uid = " . $_SESSION['uid']);
            }
            print __("You can share this article by the following unique URL:");
            $url_path = get_self_url_prefix();
            $url_path .= "/public.php?op=share&key={$uuid}";
            print "<div class=\"tagCloudContainer\">";
            print "<a id='pub_opml_url' href='{$url_path}' target='_blank'>{$url_path}</a>";
            print "</div>";
            /* if (!label_find_id($link, __('Shared'), $_SESSION["uid"]))
            					label_create($link, __('Shared'), $_SESSION["uid"]);
            
            				label_add_article($link, $ref_id, __('Shared'), $_SESSION['uid']); */
        }
        print "<div align='center'>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('shareArticleDlg').hide()\">" . __('Close this window') . "</button>";
        print "</div>";
        return;
    }
    print "</dlg>";
}
Beispiel #12
0
/**
 * Compute the Mozilla Firefox feed adding URL from server HOST and REQUEST_URI.
 *
 * @return string The Mozilla Firefox feed adding URL.
 */
function add_feed_url()
{
    //$url_path = ($_SERVER['HTTPS'] != "on" ? 'http://' :  'https://') . $_SERVER["HTTP_HOST"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
    $url_path = get_self_url_prefix() . "/backend.php?op=pref-feeds&quiet=1&subop=add&feed_url=%s";
    return $url_path;
}
Beispiel #13
0
function update_rss_feed($feed, $ignore_daemon = false, $no_cache = false, $rss = false)
{
    $debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
    _debug_suppress(!$debug_enabled);
    _debug("start", $debug_enabled);
    $result = db_query("SELECT title FROM ttrss_feeds\n\t\t\tWHERE id = '{$feed}'");
    $title = db_fetch_result($result, 0, "title");
    // feed was batch-subscribed or something, we need to get basic info
    // this is not optimal currently as it fetches stuff separately TODO: optimize
    if ($title == "[Unknown]") {
        _debug("setting basic feed info for {$feed}...");
        set_basic_feed_info($feed);
    }
    $result = db_query("SELECT id,update_interval,auth_login,\n\t\t\tfeed_url,auth_pass,cache_images,\n\t\t\tmark_unread_on_update, owner_uid,\n\t\t\tpubsub_state, auth_pass_encrypted,\n\t\t\tfeed_language,\n\t\t\t(SELECT max(date_entered) FROM\n\t\t\t\tttrss_entries, ttrss_user_entries where ref_id = id AND feed_id = '{$feed}') AS last_article_timestamp\n\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
    if (db_num_rows($result) == 0) {
        _debug("feed {$feed} NOT FOUND/SKIPPED", $debug_enabled);
        return false;
    }
    $last_article_timestamp = @strtotime(db_fetch_result($result, 0, "last_article_timestamp"));
    if (defined('_DISABLE_HTTP_304')) {
        $last_article_timestamp = 0;
    }
    $owner_uid = db_fetch_result($result, 0, "owner_uid");
    $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
    $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
    $auth_pass_encrypted = sql_bool_to_bool(db_fetch_result($result, 0, "auth_pass_encrypted"));
    db_query("UPDATE ttrss_feeds SET last_update_started = NOW()\n\t\t\tWHERE id = '{$feed}'");
    $auth_login = db_fetch_result($result, 0, "auth_login");
    $auth_pass = db_fetch_result($result, 0, "auth_pass");
    if ($auth_pass_encrypted) {
        require_once "crypt.php";
        $auth_pass = decrypt_string($auth_pass);
    }
    $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
    $fetch_url = db_fetch_result($result, 0, "feed_url");
    $feed_language = db_escape_string(mb_strtolower(db_fetch_result($result, 0, "feed_language")));
    if (!$feed_language) {
        $feed_language = 'english';
    }
    $feed = db_escape_string($feed);
    $date_feed_processed = date('Y-m-d H:i');
    $cache_filename = CACHE_DIR . "/simplepie/" . sha1($fetch_url) . ".xml";
    $pluginhost = new PluginHost();
    $pluginhost->set_debug($debug_enabled);
    $user_plugins = get_pref("_ENABLED_PLUGINS", $owner_uid);
    $pluginhost->load(PLUGINS, PluginHost::KIND_ALL);
    $pluginhost->load($user_plugins, PluginHost::KIND_USER, $owner_uid);
    $pluginhost->load_data();
    if ($rss && is_object($rss) && get_class($rss) == "FeedParser") {
        _debug("using previously initialized parser object");
    } else {
        $rss_hash = false;
        $force_refetch = isset($_REQUEST["force_refetch"]);
        foreach ($pluginhost->get_hooks(PluginHost::HOOK_FETCH_FEED) as $plugin) {
            $feed_data = $plugin->hook_fetch_feed($feed_data, $fetch_url, $owner_uid, $feed, $last_article_timestamp, $auth_login, $auth_pass);
        }
        // try cache
        if (!$feed_data && file_exists($cache_filename) && is_readable($cache_filename) && !$auth_login && !$auth_pass && filemtime($cache_filename) > time() - 30) {
            _debug("using local cache [{$cache_filename}].", $debug_enabled);
            @($feed_data = file_get_contents($cache_filename));
            if ($feed_data) {
                $rss_hash = sha1($feed_data);
            }
        } else {
            _debug("local cache will not be used for this feed", $debug_enabled);
        }
        // fetch feed from source
        if (!$feed_data) {
            _debug("fetching [{$fetch_url}]...", $debug_enabled);
            _debug("If-Modified-Since: " . gmdate('D, d M Y H:i:s \\G\\M\\T', $last_article_timestamp), $debug_enabled);
            $feed_data = fetch_file_contents($fetch_url, false, $auth_login, $auth_pass, false, $no_cache ? FEED_FETCH_NO_CACHE_TIMEOUT : FEED_FETCH_TIMEOUT, $force_refetch ? 0 : $last_article_timestamp);
            global $fetch_curl_used;
            if (!$fetch_curl_used) {
                $tmp = @gzdecode($feed_data);
                if ($tmp) {
                    $feed_data = $tmp;
                }
            }
            $feed_data = trim($feed_data);
            _debug("fetch done.", $debug_enabled);
            // cache vanilla feed data for re-use
            if ($feed_data && !$auth_pass && !$auth_login && is_writable(CACHE_DIR . "/simplepie")) {
                $new_rss_hash = sha1($feed_data);
                if ($new_rss_hash != $rss_hash) {
                    _debug("saving {$cache_filename}", $debug_enabled);
                    @file_put_contents($cache_filename, $feed_data);
                }
            }
        }
        if (!$feed_data) {
            global $fetch_last_error;
            global $fetch_last_error_code;
            _debug("unable to fetch: {$fetch_last_error} [{$fetch_last_error_code}]", $debug_enabled);
            $error_escaped = '';
            // If-Modified-Since
            if ($fetch_last_error_code != 304) {
                $error_escaped = db_escape_string($fetch_last_error);
            } else {
                _debug("source claims data not modified, nothing to do.", $debug_enabled);
            }
            db_query("UPDATE ttrss_feeds SET last_error = '{$error_escaped}',\n\t\t\t\t\t\tlast_updated = NOW() WHERE id = '{$feed}'");
            return;
        }
    }
    foreach ($pluginhost->get_hooks(PluginHost::HOOK_FEED_FETCHED) as $plugin) {
        $feed_data = $plugin->hook_feed_fetched($feed_data, $fetch_url, $owner_uid, $feed);
    }
    // set last update to now so if anything *simplepie* crashes later we won't be
    // continuously failing on the same feed
    //db_query("UPDATE ttrss_feeds SET last_updated = NOW() WHERE id = '$feed'");
    if (!$rss) {
        $rss = new FeedParser($feed_data);
        $rss->init();
    }
    //		print_r($rss);
    $feed = db_escape_string($feed);
    if (!$rss->error()) {
        // We use local pluginhost here because we need to load different per-user feed plugins
        $pluginhost->run_hooks(PluginHost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
        _debug("language: {$feed_language}", $debug_enabled);
        _debug("processing feed data...", $debug_enabled);
        //			db_query("BEGIN");
        if (DB_TYPE == "pgsql") {
            $favicon_interval_qpart = "favicon_last_checked < NOW() - INTERVAL '12 hour'";
        } else {
            $favicon_interval_qpart = "favicon_last_checked < DATE_SUB(NOW(), INTERVAL 12 HOUR)";
        }
        $result = db_query("SELECT owner_uid,favicon_avg_color,\n\t\t\t\t(favicon_last_checked IS NULL OR {$favicon_interval_qpart}) AS\n\t\t\t\t\t\tfavicon_needs_check\n\t\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
        $favicon_needs_check = sql_bool_to_bool(db_fetch_result($result, 0, "favicon_needs_check"));
        $favicon_avg_color = db_fetch_result($result, 0, "favicon_avg_color");
        $owner_uid = db_fetch_result($result, 0, "owner_uid");
        $site_url = db_escape_string(mb_substr(rewrite_relative_url($fetch_url, $rss->get_link()), 0, 245));
        _debug("site_url: {$site_url}", $debug_enabled);
        _debug("feed_title: " . $rss->get_title(), $debug_enabled);
        if ($favicon_needs_check || $force_refetch) {
            /* terrible hack: if we crash on floicon shit here, we won't check
             * the icon avgcolor again (unless the icon got updated) */
            $favicon_file = ICONS_DIR . "/{$feed}.ico";
            $favicon_modified = @filemtime($favicon_file);
            _debug("checking favicon...", $debug_enabled);
            check_feed_favicon($site_url, $feed);
            $favicon_modified_new = @filemtime($favicon_file);
            if ($favicon_modified_new > $favicon_modified) {
                $favicon_avg_color = '';
            }
            if (file_exists($favicon_file) && function_exists("imagecreatefromstring") && $favicon_avg_color == '') {
                require_once "colors.php";
                db_query("UPDATE ttrss_feeds SET favicon_avg_color = 'fail' WHERE\n\t\t\t\t\t\t\tid = '{$feed}'");
                $favicon_color = db_escape_string(calculate_avg_color($favicon_file));
                $favicon_colorstring = ",favicon_avg_color = '" . $favicon_color . "'";
            } else {
                if ($favicon_avg_color == 'fail') {
                    _debug("floicon failed on this file, not trying to recalculate avg color", $debug_enabled);
                }
            }
            db_query("UPDATE ttrss_feeds SET favicon_last_checked = NOW()\n\t\t\t\t\t{$favicon_colorstring}\n\t\t\t\t\tWHERE id = '{$feed}'");
        }
        _debug("loading filters & labels...", $debug_enabled);
        $filters = load_filters($feed, $owner_uid);
        _debug("" . count($filters) . " filters loaded.", $debug_enabled);
        $items = $rss->get_items();
        if (!is_array($items)) {
            _debug("no articles found.", $debug_enabled);
            db_query("UPDATE ttrss_feeds\n\t\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
            return;
            // no articles
        }
        if ($pubsub_state != 2 && PUBSUBHUBBUB_ENABLED) {
            _debug("checking for PUSH hub...", $debug_enabled);
            $feed_hub_url = false;
            $links = $rss->get_links('hub');
            if ($links && is_array($links)) {
                foreach ($links as $l) {
                    $feed_hub_url = $l;
                    break;
                }
            }
            _debug("feed hub url: {$feed_hub_url}", $debug_enabled);
            $feed_self_url = $fetch_url;
            $links = $rss->get_links('self');
            if ($links && is_array($links)) {
                foreach ($links as $l) {
                    $feed_self_url = $l;
                    break;
                }
            }
            _debug("feed self url = {$feed_self_url}");
            if ($feed_hub_url && $feed_self_url && function_exists('curl_init') && !ini_get("open_basedir")) {
                require_once 'lib/pubsubhubbub/subscriber.php';
                $callback_url = get_self_url_prefix() . "/public.php?op=pubsub&id={$feed}";
                $s = new Subscriber($feed_hub_url, $callback_url);
                $rc = $s->subscribe($feed_self_url);
                _debug("feed hub url found, subscribe request sent. [rc={$rc}]", $debug_enabled);
                db_query("UPDATE ttrss_feeds SET pubsub_state = 1\n\t\t\t\t\t\tWHERE id = '{$feed}'");
            }
        }
        _debug("processing articles...", $debug_enabled);
        $tstart = time();
        foreach ($items as $item) {
            if ($_REQUEST['xdebug'] == 3) {
                print_r($item);
            }
            if (ini_get("max_execution_time") > 0 && time() - $tstart >= ini_get("max_execution_time") * 0.7) {
                _debug("looks like there's too many articles to process at once, breaking out", $debug_enabled);
                break;
            }
            $entry_guid = $item->get_id();
            if (!$entry_guid) {
                $entry_guid = $item->get_link();
            }
            if (!$entry_guid) {
                $entry_guid = make_guid_from_title($item->get_title());
            }
            if (!$entry_guid) {
                continue;
            }
            $entry_guid = "{$owner_uid},{$entry_guid}";
            $entry_guid_hashed = db_escape_string('SHA1:' . sha1($entry_guid));
            _debug("guid {$entry_guid} / {$entry_guid_hashed}", $debug_enabled);
            $entry_timestamp = "";
            $entry_timestamp = $item->get_date();
            _debug("orig date: " . $item->get_date(), $debug_enabled);
            if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
                $entry_timestamp = time();
            }
            $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
            _debug("date {$entry_timestamp} [{$entry_timestamp_fmt}]", $debug_enabled);
            //				$entry_title = html_entity_decode($item->get_title(), ENT_COMPAT, 'UTF-8');
            //				$entry_title = decode_numeric_entities($entry_title);
            $entry_title = $item->get_title();
            $entry_link = rewrite_relative_url($site_url, $item->get_link());
            _debug("title {$entry_title}", $debug_enabled);
            _debug("link {$entry_link}", $debug_enabled);
            if (!$entry_title) {
                $entry_title = date("Y-m-d H:i:s", $entry_timestamp);
            }
            $entry_content = $item->get_content();
            if (!$entry_content) {
                $entry_content = $item->get_description();
            }
            if ($_REQUEST["xdebug"] == 2) {
                print "content: ";
                print $entry_content;
                print "\n";
            }
            $entry_comments = $item->get_comments_url();
            $entry_author = $item->get_author();
            $entry_guid = db_escape_string(mb_substr($entry_guid, 0, 245));
            $entry_comments = db_escape_string(mb_substr(trim($entry_comments), 0, 245));
            $entry_author = db_escape_string(mb_substr(trim($entry_author), 0, 245));
            $num_comments = (int) $item->get_comments_count();
            _debug("author {$entry_author}", $debug_enabled);
            _debug("num_comments: {$num_comments}", $debug_enabled);
            _debug("looking for tags...", $debug_enabled);
            // parse <category> entries into tags
            $additional_tags = array();
            $additional_tags_src = $item->get_categories();
            if (is_array($additional_tags_src)) {
                foreach ($additional_tags_src as $tobj) {
                    array_push($additional_tags, $tobj);
                }
            }
            $entry_tags = array_unique($additional_tags);
            for ($i = 0; $i < count($entry_tags); $i++) {
                $entry_tags[$i] = mb_strtolower($entry_tags[$i], 'utf-8');
            }
            _debug("tags found: " . join(",", $entry_tags), $debug_enabled);
            _debug("done collecting data.", $debug_enabled);
            $result = db_query("SELECT id, content_hash, lang FROM ttrss_entries\n\t\t\t\t\tWHERE guid = '" . db_escape_string($entry_guid) . "' OR guid = '{$entry_guid_hashed}'");
            if (db_num_rows($result) != 0) {
                $base_entry_id = db_fetch_result($result, 0, "id");
                $entry_stored_hash = db_fetch_result($result, 0, "content_hash");
                $article_labels = get_article_labels($base_entry_id, $owner_uid);
                $entry_language = db_fetch_result($result, 0, "lang");
            } else {
                $base_entry_id = false;
                $entry_stored_hash = "";
                $article_labels = array();
                $entry_language = "";
            }
            $article = array("owner_uid" => $owner_uid, "guid" => $entry_guid, "guid_hashed" => $entry_guid_hashed, "title" => $entry_title, "content" => $entry_content, "link" => $entry_link, "labels" => $article_labels, "tags" => $entry_tags, "author" => $entry_author, "force_catchup" => false, "score_modifier" => 0, "language" => $entry_language, "feed" => array("id" => $feed, "fetch_url" => $fetch_url, "site_url" => $site_url));
            $entry_plugin_data = "";
            $entry_current_hash = calculate_article_hash($article, $pluginhost);
            _debug("article hash: {$entry_current_hash} [stored={$entry_stored_hash}]", $debug_enabled);
            if ($entry_current_hash == $entry_stored_hash && !isset($_REQUEST["force_rehash"])) {
                _debug("stored article seems up to date [IID: {$base_entry_id}], updating timestamp only", $debug_enabled);
                // we keep encountering the entry in feeds, so we need to
                // update date_updated column so that we don't get horrible
                // dupes when the entry gets purged and reinserted again e.g.
                // in the case of SLOW SLOW OMG SLOW updating feeds
                $base_entry_id = db_fetch_result($result, 0, "id");
                db_query("UPDATE ttrss_entries SET date_updated = NOW()\n\t\t\t\t\t\tWHERE id = '{$base_entry_id}'");
                // if we allow duplicate posts, we have to continue to
                // create the user entries for this feed
                if (!get_pref("ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
                    continue;
                }
            }
            _debug("hash differs, applying plugin filters:", $debug_enabled);
            foreach ($pluginhost->get_hooks(PluginHost::HOOK_ARTICLE_FILTER) as $plugin) {
                _debug("... " . get_class($plugin), $debug_enabled);
                $start = microtime(true);
                $article = $plugin->hook_article_filter($article);
                _debug("=== " . sprintf("%.4f (sec)", microtime(true) - $start), $debug_enabled);
                $entry_plugin_data .= mb_strtolower(get_class($plugin)) . ",";
            }
            $entry_plugin_data = db_escape_string($entry_plugin_data);
            _debug("plugin data: {$entry_plugin_data}", $debug_enabled);
            // Workaround: 4-byte unicode requires utf8mb4 in MySQL. See https://tt-rss.org/forum/viewtopic.php?f=1&t=3377&p=20077#p20077
            if (DB_TYPE == "mysql") {
                foreach ($article as $k => $v) {
                    // i guess we'll have to take the risk of 4byte unicode labels & tags here
                    if (!is_array($article[$k])) {
                        $article[$k] = preg_replace('/[\\x{10000}-\\x{10FFFF}]/u', "�", $v);
                    }
                }
            }
            $entry_tags = $article["tags"];
            $entry_guid = db_escape_string($entry_guid);
            $entry_title = db_escape_string($article["title"]);
            $entry_author = db_escape_string($article["author"]);
            $entry_link = db_escape_string($article["link"]);
            $entry_content = $article["content"];
            // escaped below
            $entry_force_catchup = $article["force_catchup"];
            $article_labels = $article["labels"];
            $entry_score_modifier = (int) $article["score_modifier"];
            $entry_language = db_escape_string($article["language"]);
            if ($debug_enabled) {
                _debug("article labels:", $debug_enabled);
                print_r($article_labels);
            }
            _debug("force catchup: {$entry_force_catchup}");
            if ($cache_images && is_writable(CACHE_DIR . '/images')) {
                cache_images($entry_content, $site_url, $debug_enabled);
            }
            $entry_content = db_escape_string($entry_content, false);
            db_query("BEGIN");
            $result = db_query("SELECT id FROM\tttrss_entries\n\t\t\t\t\tWHERE (guid = '{$entry_guid}' OR guid = '{$entry_guid_hashed}')");
            if (db_num_rows($result) == 0) {
                _debug("base guid [{$entry_guid}] not found", $debug_enabled);
                // base post entry does not exist, create it
                $result = db_query("INSERT INTO ttrss_entries\n\t\t\t\t\t\t\t(title,\n\t\t\t\t\t\t\tguid,\n\t\t\t\t\t\t\tlink,\n\t\t\t\t\t\t\tupdated,\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tcontent_hash,\n\t\t\t\t\t\t\tno_orig_date,\n\t\t\t\t\t\t\tdate_updated,\n\t\t\t\t\t\t\tdate_entered,\n\t\t\t\t\t\t\tcomments,\n\t\t\t\t\t\t\tnum_comments,\n\t\t\t\t\t\t\tplugin_data,\n\t\t\t\t\t\t\tlang,\n\t\t\t\t\t\t\tauthor)\n\t\t\t\t\t\tVALUES\n\t\t\t\t\t\t\t('{$entry_title}',\n\t\t\t\t\t\t\t'{$entry_guid_hashed}',\n\t\t\t\t\t\t\t'{$entry_link}',\n\t\t\t\t\t\t\t'{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t'{$entry_content}',\n\t\t\t\t\t\t\t'{$entry_current_hash}',\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tNOW(),\n\t\t\t\t\t\t\t'{$date_feed_processed}',\n\t\t\t\t\t\t\t'{$entry_comments}',\n\t\t\t\t\t\t\t'{$num_comments}',\n\t\t\t\t\t\t\t'{$entry_plugin_data}',\n\t\t\t\t\t\t\t'{$entry_language}',\n\t\t\t\t\t\t\t'{$entry_author}')");
            } else {
                $base_entry_id = db_fetch_result($result, 0, "id");
            }
            // now it should exist, if not - bad luck then
            $result = db_query("SELECT id FROM ttrss_entries\n\t\t\t\t\tWHERE guid = '{$entry_guid}' OR guid = '{$entry_guid_hashed}'");
            $entry_ref_id = 0;
            $entry_int_id = 0;
            if (db_num_rows($result) == 1) {
                _debug("base guid found, checking for user record", $debug_enabled);
                $ref_id = db_fetch_result($result, 0, "id");
                $entry_ref_id = $ref_id;
                /* $stored_guid = db_fetch_result($result, 0, "guid");
                					if ($stored_guid != $entry_guid_hashed) {
                						if ($debug_enabled) _debug("upgrading compat guid to hashed one", $debug_enabled);
                
                						db_query("UPDATE ttrss_entries SET guid = '$entry_guid_hashed' WHERE
                							id = '$ref_id'");
                					} */
                // check for user post link to main table
                // do we allow duplicate posts with same GUID in different feeds?
                if (get_pref("ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
                    $dupcheck_qpart = "AND (feed_id = '{$feed}' OR feed_id IS NULL)";
                } else {
                    $dupcheck_qpart = "";
                }
                /* Collect article tags here so we could filter by them: */
                $article_filters = get_article_filters($filters, $entry_title, $entry_content, $entry_link, $entry_timestamp, $entry_author, $entry_tags);
                if ($debug_enabled) {
                    _debug("article filters: ", $debug_enabled);
                    if (count($article_filters) != 0) {
                        print_r($article_filters);
                    }
                }
                if (find_article_filter($article_filters, "filter")) {
                    db_query("COMMIT");
                    // close transaction in progress
                    continue;
                }
                $score = calculate_article_score($article_filters) + $entry_score_modifier;
                _debug("initial score: {$score} [including plugin modifier: {$entry_score_modifier}]", $debug_enabled);
                $query = "SELECT ref_id, int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}'\n\t\t\t\t\t\t\t{$dupcheck_qpart}";
                //					if ($_REQUEST["xdebug"]) print "$query\n";
                $result = db_query($query);
                // okay it doesn't exist - create user entry
                if (db_num_rows($result) == 0) {
                    _debug("user record not found, creating...", $debug_enabled);
                    if ($score >= -500 && !find_article_filter($article_filters, 'catchup') && !$entry_force_catchup) {
                        $unread = 'true';
                        $last_read_qpart = 'NULL';
                    } else {
                        $unread = 'false';
                        $last_read_qpart = 'NOW()';
                    }
                    if (find_article_filter($article_filters, 'mark') || $score > 1000) {
                        $marked = 'true';
                    } else {
                        $marked = 'false';
                    }
                    if (find_article_filter($article_filters, 'publish')) {
                        $published = 'true';
                    } else {
                        $published = 'false';
                    }
                    // N-grams
                    /* if (DB_TYPE == "pgsql" and defined('_NGRAM_TITLE_DUPLICATE_THRESHOLD')) {
                    
                    							$result = db_query("SELECT COUNT(*) AS similar FROM
                    									ttrss_entries,ttrss_user_entries
                    								WHERE ref_id = id AND updated >= NOW() - INTERVAL '7 day'
                    									AND similarity(title, '$entry_title') >= "._NGRAM_TITLE_DUPLICATE_THRESHOLD."
                    									AND owner_uid = $owner_uid");
                    
                    							$ngram_similar = db_fetch_result($result, 0, "similar");
                    
                    							_debug("N-gram similar results: $ngram_similar", $debug_enabled);
                    
                    							if ($ngram_similar > 0) {
                    								$unread = 'false';
                    							}
                    						} */
                    $last_marked = $marked == 'true' ? 'NOW()' : 'NULL';
                    $last_published = $published == 'true' ? 'NOW()' : 'NULL';
                    $result = db_query("INSERT INTO ttrss_user_entries\n\t\t\t\t\t\t\t\t(ref_id, owner_uid, feed_id, unread, last_read, marked,\n\t\t\t\t\t\t\t\tpublished, score, tag_cache, label_cache, uuid,\n\t\t\t\t\t\t\t\tlast_marked, last_published)\n\t\t\t\t\t\t\tVALUES ('{$ref_id}', '{$owner_uid}', '{$feed}', {$unread},\n\t\t\t\t\t\t\t\t{$last_read_qpart}, {$marked}, {$published}, '{$score}', '', '',\n\t\t\t\t\t\t\t\t'', {$last_marked}, {$last_published})");
                    if (PUBSUBHUBBUB_HUB && $published == 'true') {
                        $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key(-2, false, $owner_uid);
                        $p = new Publisher(PUBSUBHUBBUB_HUB);
                        /* $pubsub_result = */
                        $p->publish_update($rss_link);
                    }
                    $result = db_query("SELECT int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}' AND\n\t\t\t\t\t\t\t\tfeed_id = '{$feed}' LIMIT 1");
                    if (db_num_rows($result) == 1) {
                        $entry_int_id = db_fetch_result($result, 0, "int_id");
                    }
                } else {
                    _debug("user record FOUND", $debug_enabled);
                    $entry_ref_id = db_fetch_result($result, 0, "ref_id");
                    $entry_int_id = db_fetch_result($result, 0, "int_id");
                }
                _debug("RID: {$entry_ref_id}, IID: {$entry_int_id}", $debug_enabled);
                if (DB_TYPE == "pgsql") {
                    $tsvector_combined = db_escape_string(mb_substr($entry_title . ' ' . strip_tags($entry_content), 0, 1000000));
                    $tsvector_qpart = "tsvector_combined = to_tsvector('{$feed_language}', '{$tsvector_combined}'),";
                } else {
                    $tsvector_qpart = "";
                }
                db_query("UPDATE ttrss_entries\n\t\t\t\t\t\tSET title = '{$entry_title}',\n\t\t\t\t\t\t\tcontent = '{$entry_content}',\n\t\t\t\t\t\t\tcontent_hash = '{$entry_current_hash}',\n\t\t\t\t\t\t\tupdated = '{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t{$tsvector_qpart}\n\t\t\t\t\t\t\tnum_comments = '{$num_comments}',\n\t\t\t\t\t\t\tplugin_data = '{$entry_plugin_data}',\n\t\t\t\t\t\t\tauthor = '{$entry_author}',\n\t\t\t\t\t\t\tlang = '{$entry_language}'\n\t\t\t\t\t\tWHERE id = '{$ref_id}'");
                // update aux data
                db_query("UPDATE ttrss_user_entries\n\t\t\t\t\t\t\tSET score = '{$score}' WHERE ref_id = '{$ref_id}'");
                if ($mark_unread_on_update) {
                    db_query("UPDATE ttrss_user_entries\n\t\t\t\t\t\t\tSET last_read = null, unread = true WHERE ref_id = '{$ref_id}'");
                }
            }
            db_query("COMMIT");
            _debug("assigning labels [other]...", $debug_enabled);
            foreach ($article_labels as $label) {
                label_add_article($entry_ref_id, $label[1], $owner_uid);
            }
            _debug("assigning labels [filters]...", $debug_enabled);
            assign_article_to_label_filters($entry_ref_id, $article_filters, $owner_uid, $article_labels);
            _debug("looking for enclosures...", $debug_enabled);
            // enclosures
            $enclosures = array();
            $encs = $item->get_enclosures();
            if (is_array($encs)) {
                foreach ($encs as $e) {
                    $e_item = array($e->link, $e->type, $e->length, $e->title, $e->width, $e->height);
                    array_push($enclosures, $e_item);
                }
            }
            if ($debug_enabled) {
                _debug("article enclosures:", $debug_enabled);
                print_r($enclosures);
            }
            db_query("BEGIN");
            //				debugging
            //				db_query("DELETE FROM ttrss_enclosures WHERE post_id = '$entry_ref_id'");
            foreach ($enclosures as $enc) {
                $enc_url = db_escape_string($enc[0]);
                $enc_type = db_escape_string($enc[1]);
                $enc_dur = db_escape_string($enc[2]);
                $enc_title = db_escape_string($enc[3]);
                $enc_width = intval($enc[4]);
                $enc_height = intval($enc[5]);
                $result = db_query("SELECT id FROM ttrss_enclosures\n\t\t\t\t\t\tWHERE content_url = '{$enc_url}' AND post_id = '{$entry_ref_id}'");
                if (db_num_rows($result) == 0) {
                    db_query("INSERT INTO ttrss_enclosures\n\t\t\t\t\t\t\t(content_url, content_type, title, duration, post_id, width, height) VALUES\n\t\t\t\t\t\t\t('{$enc_url}', '{$enc_type}', '{$enc_title}', '{$enc_dur}', '{$entry_ref_id}', {$enc_width}, {$enc_height})");
                }
            }
            db_query("COMMIT");
            // check for manual tags (we have to do it here since they're loaded from filters)
            foreach ($article_filters as $f) {
                if ($f["type"] == "tag") {
                    $manual_tags = trim_array(explode(",", $f["param"]));
                    foreach ($manual_tags as $tag) {
                        if (tag_is_valid($tag)) {
                            array_push($entry_tags, $tag);
                        }
                    }
                }
            }
            // Skip boring tags
            $boring_tags = trim_array(explode(",", mb_strtolower(get_pref('BLACKLISTED_TAGS', $owner_uid, ''), 'utf-8')));
            $filtered_tags = array();
            $tags_to_cache = array();
            if ($entry_tags && is_array($entry_tags)) {
                foreach ($entry_tags as $tag) {
                    if (array_search($tag, $boring_tags) === false) {
                        array_push($filtered_tags, $tag);
                    }
                }
            }
            $filtered_tags = array_unique($filtered_tags);
            if ($debug_enabled) {
                _debug("filtered article tags:", $debug_enabled);
                print_r($filtered_tags);
            }
            // Save article tags in the database
            if (count($filtered_tags) > 0) {
                db_query("BEGIN");
                foreach ($filtered_tags as $tag) {
                    $tag = sanitize_tag($tag);
                    $tag = db_escape_string($tag);
                    if (!tag_is_valid($tag)) {
                        continue;
                    }
                    $result = db_query("SELECT id FROM ttrss_tags\n\t\t\t\t\t\t\tWHERE tag_name = '{$tag}' AND post_int_id = '{$entry_int_id}' AND\n\t\t\t\t\t\t\towner_uid = '{$owner_uid}' LIMIT 1");
                    if ($result && db_num_rows($result) == 0) {
                        db_query("INSERT INTO ttrss_tags\n\t\t\t\t\t\t\t\t\t(owner_uid,tag_name,post_int_id)\n\t\t\t\t\t\t\t\t\tVALUES ('{$owner_uid}','{$tag}', '{$entry_int_id}')");
                    }
                    array_push($tags_to_cache, $tag);
                }
                /* update the cache */
                $tags_to_cache = array_unique($tags_to_cache);
                $tags_str = db_escape_string(join(",", $tags_to_cache));
                db_query("UPDATE ttrss_user_entries\n\t\t\t\t\t\tSET tag_cache = '{$tags_str}' WHERE ref_id = '{$entry_ref_id}'\n\t\t\t\t\t\tAND owner_uid = {$owner_uid}");
                db_query("COMMIT");
            }
            _debug("article processed", $debug_enabled);
        }
        _debug("purging feed...", $debug_enabled);
        purge_feed($feed, 0, $debug_enabled);
        db_query("UPDATE ttrss_feeds\n\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
        //			db_query("COMMIT");
    } else {
        $error_msg = db_escape_string(mb_substr($rss->error(), 0, 245));
        _debug("fetch error: {$error_msg}", $debug_enabled);
        if (count($rss->errors()) > 1) {
            foreach ($rss->errors() as $error) {
                _debug("+ {$error}");
            }
        }
        db_query("UPDATE ttrss_feeds SET last_error = '{$error_msg}',\n\t\t\t\tlast_updated = NOW() WHERE id = '{$feed}'");
        unset($rss);
    }
    _debug("done", $debug_enabled);
    return $rss;
}
Beispiel #14
0
 function forgotpass()
 {
     startup_gettext();
     @($hash = $_REQUEST["hash"]);
     header('Content-Type: text/html; charset=utf-8');
     print "<html><head><title>Tiny Tiny RSS</title>\n\t\t<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">\n\t\t<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">";
     echo stylesheet_tag("css/utility.css");
     echo javascript_tag("lib/prototype.js");
     print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n\t\t\t</head><body id='forgotpass'>";
     print '<div class="floatingLogo"><img src="images/logo_small.png"></div>';
     print "<h1>" . __("Password recovery") . "</h1>";
     print "<div class='content'>";
     @($method = $_POST['method']);
     if ($hash) {
         $login = $_REQUEST["login"];
         if ($login) {
             $result = $this->dbh->query("SELECT id, resetpass_token FROM ttrss_users\n\t\t\t\t\tWHERE login = '******'");
             if ($this->dbh->num_rows($result) != 0) {
                 $id = $this->dbh->fetch_result($result, 0, "id");
                 $resetpass_token_full = $this->dbh->fetch_result($result, 0, "resetpass_token");
                 list($timestamp, $resetpass_token) = explode(":", $resetpass_token_full);
                 if ($timestamp && $resetpass_token && $timestamp >= time() - 15 * 60 * 60 && $resetpass_token == $hash) {
                     $result = $this->dbh->query("UPDATE ttrss_users SET resetpass_token = NULL\n\t\t\t\t\t\t\t\tWHERE id = {$id}");
                     Pref_Users::resetUserPassword($id, true);
                     print "<p>" . "Completed." . "</p>";
                 } else {
                     print_error("Some of the information provided is missing or incorrect.");
                 }
             } else {
                 print_error("Some of the information provided is missing or incorrect.");
             }
         } else {
             print_error("Some of the information provided is missing or incorrect.");
         }
         print "<form method=\"GET\" action=\"index.php\">\n\t\t\t\t<input type=\"submit\" value=\"" . __("Return to Tiny Tiny RSS") . "\">\n\t\t\t\t</form>";
     } else {
         if (!$method) {
             print_notice(__("You will need to provide valid account name and email. A password reset link will be sent to your email address."));
             print "<form method='POST' action='public.php'>";
             print "<input type='hidden' name='method' value='do'>";
             print "<input type='hidden' name='op' value='forgotpass'>";
             print "<fieldset>";
             print "<label>" . __("Login:"******"</label>";
             print "<input type='text' name='login' value='' required>";
             print "</fieldset>";
             print "<fieldset>";
             print "<label>" . __("Email:") . "</label>";
             print "<input type='email' name='email' value='' required>";
             print "</fieldset>";
             print "<fieldset>";
             print "<label>" . __("How much is two plus two:") . "</label>";
             print "<input type='text' name='test' value='' required>";
             print "</fieldset>";
             print "<p/>";
             print "<button type='submit'>" . __("Reset password") . "</button>";
             print "</form>";
         } else {
             if ($method == 'do') {
                 $login = $this->dbh->escape_string($_POST["login"]);
                 $email = $this->dbh->escape_string($_POST["email"]);
                 $test = $this->dbh->escape_string($_POST["test"]);
                 if ($test != 4 && $test != 'four' || !$email || !$login) {
                     print_error(__('Some of the required form parameters are missing or incorrect.'));
                     print "<form method=\"GET\" action=\"public.php\">\n\t\t\t\t\t<input type=\"hidden\" name=\"op\" value=\"forgotpass\">\n\t\t\t\t\t<input type=\"submit\" value=\"" . __("Go back") . "\">\n\t\t\t\t\t</form>";
                 } else {
                     print_notice("Password reset instructions are being sent to your email address.");
                     $result = $this->dbh->query("SELECT id FROM ttrss_users\n\t\t\t\t\tWHERE login = '******' AND email = '{$email}'");
                     if ($this->dbh->num_rows($result) != 0) {
                         $id = $this->dbh->fetch_result($result, 0, "id");
                         if ($id) {
                             $resetpass_token = sha1(get_random_bytes(128));
                             $resetpass_link = get_self_url_prefix() . "/public.php?op=forgotpass&hash=" . $resetpass_token . "&login="******"lib/MiniTemplator.class.php";
                             $tpl = new MiniTemplator();
                             $tpl->readTemplateFromFile("templates/resetpass_link_template.txt");
                             $tpl->setVariable('LOGIN', $login);
                             $tpl->setVariable('RESETPASS_LINK', $resetpass_link);
                             $tpl->addBlock('message');
                             $message = "";
                             $tpl->generateOutputToString($message);
                             $mail = new ttrssMailer();
                             $rc = $mail->quickMail($email, $login, __("[tt-rss] Password reset request"), $message, false);
                             if (!$rc) {
                                 print_error($mail->ErrorInfo);
                             }
                             $resetpass_token_full = $this->dbh->escape_string(time() . ":" . $resetpass_token);
                             $result = $this->dbh->query("UPDATE ttrss_users\n\t\t\t\t\t\t\tSET resetpass_token = '{$resetpass_token_full}'\n\t\t\t\t\t\t\tWHERE login = '******' AND email = '{$email}'");
                             //Pref_Users::resetUserPassword($id, false);
                             print "<p>";
                             print "<p>" . "Completed." . "</p>";
                         } else {
                             print_error("User ID not found.");
                         }
                         print "<form method=\"GET\" action=\"index.php\">\n\t\t\t\t\t\t<input type=\"submit\" value=\"" . __("Return to Tiny Tiny RSS") . "\">\n\t\t\t\t\t\t</form>";
                     } else {
                         print_error(__("Sorry, login and email combination not found."));
                         print "<form method=\"GET\" action=\"public.php\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"op\" value=\"forgotpass\">\n\t\t\t\t\t\t<input type=\"submit\" value=\"" . __("Go back") . "\">\n\t\t\t\t\t\t</form>";
                     }
                 }
             }
         }
     }
     print "</div>";
     print "</body>";
     print "</html>";
 }
Beispiel #15
0
 private function make_article_tag_uri($id, $timestamp)
 {
     $timestamp = date("Y-m-d", strtotime($timestamp));
     return "tag:" . parse_url(get_self_url_prefix(), PHP_URL_HOST) . ",{$timestamp}:/{$id}";
 }
Beispiel #16
0
function module_pref_instances($link)
{
    if (!SINGLE_USER_MODE && $_SESSION["access_level"] < 10) {
        print __("Your access level is insufficient to open this tab.");
        return;
    }
    $subop = $_REQUEST['subop'];
    if ($subop == "remove") {
        $ids = db_escape_string($_REQUEST['ids']);
        db_query($link, "DELETE FROM ttrss_linked_instances WHERE\n\t\t\t\tid IN ({$ids})");
        return;
    }
    if ($subop == "add") {
        $id = db_escape_string($_REQUEST["id"]);
        $access_url = db_escape_string($_REQUEST["access_url"]);
        $access_key = db_escape_string($_REQUEST["access_key"]);
        db_query($link, "BEGIN");
        $result = db_query($link, "SELECT id FROM ttrss_linked_instances\n\t\t\t\tWHERE access_url = '{$access_url}'");
        if (db_num_rows($result) == 0) {
            db_query($link, "INSERT INTO ttrss_linked_instances\n\t\t\t\t\t(access_url, access_key, last_connected, last_status_in, last_status_out)\n\t\t\t\t\tVALUES\n\t\t\t\t\t('{$access_url}', '{$access_key}', '1970-01-01', -1, -1)");
        }
        db_query($link, "COMMIT");
        return;
    }
    if ($subop == "edit") {
        $id = db_escape_string($_REQUEST["id"]);
        $result = db_query($link, "SELECT * FROM ttrss_linked_instances WHERE\n\t\t\t\tid = '{$id}'");
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\"  name=\"id\" value=\"{$id}\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\"  name=\"op\" value=\"pref-instances\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\"  name=\"subop\" value=\"editSave\">";
        print "<div class=\"dlgSec\">" . __("Instance") . "</div>";
        print "<div class=\"dlgSecCont\">";
        /* URL */
        $access_url = htmlspecialchars(db_fetch_result($result, 0, "access_url"));
        print __("URL:") . " ";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"\n\t\t\t\tplaceHolder=\"" . __("Instance URL") . "\"\n\t\t\t\tregExp='^(http|https)://.*'\n\t\t\t\tstyle=\"font-size : 16px; width: 20em\" name=\"access_url\"\n\t\t\t\tvalue=\"{$access_url}\">";
        print "<hr/>";
        $access_key = htmlspecialchars(db_fetch_result($result, 0, "access_key"));
        /* Access key */
        print __("Access key:") . " ";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"\n\t\t\t\tplaceHolder=\"" . __("Access key") . "\" regExp='\\w{40}'\n\t\t\t\tstyle=\"width: 20em\" name=\"access_key\" id=\"instance_edit_key\"\n\t\t\t\tvalue=\"{$access_key}\">";
        print "<p class='insensitive'>" . __("Use one access key for both linked instances.");
        print "</div>";
        print "<div class=\"dlgButtons\">\n\t\t\t\t<div style='float : left'>\n\t\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\t\t\tonclick=\"return dijit.byId('instanceEditDlg').regenKey()\">" . __('Generate new key') . "</button>\n\t\t\t\t</div>\n\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\t\tonclick=\"return dijit.byId('instanceEditDlg').execute()\">" . __('Save') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\t\tonclick=\"return dijit.byId('instanceEditDlg').hide()\"\">" . __('Cancel') . "</button></div>";
        return;
    }
    if ($subop == "editSave") {
        $id = db_escape_string($_REQUEST["id"]);
        $access_url = db_escape_string($_REQUEST["access_url"]);
        $access_key = db_escape_string($_REQUEST["access_key"]);
        db_query($link, "UPDATE ttrss_linked_instances SET\n\t\t\t\taccess_key = '{$access_key}', access_url = '{$access_url}',\n\t\t\t\tlast_connected = '1970-01-01'\n\t\t\t\tWHERE id = '{$id}'");
        return;
    }
    if (!function_exists('curl_init')) {
        print "<div style='padding : 1em'>";
        print_error("This functionality requires CURL functions. Please enable CURL in your PHP configuration (you might also want to disable open_basedir in php.ini) and reload this page.");
        print "</div>";
    }
    print "<div id=\"pref-instance-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
    print "<div id=\"pref-instance-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
    print "<div id=\"pref-instance-toolbar\" dojoType=\"dijit.Toolbar\">";
    $sort = db_escape_string($_REQUEST["sort"]);
    if (!$sort || $sort == "undefined") {
        $sort = "access_url";
    }
    print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Select') . "</span>";
    print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
    print "<div onclick=\"selectTableRows('prefInstanceList', 'all')\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('All') . "</div>";
    print "<div onclick=\"selectTableRows('prefInstanceList', 'none')\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('None') . "</div>";
    print "</div></div>";
    print "<button dojoType=\"dijit.form.Button\" onclick=\"addInstance()\">" . __('Link instance') . "</button>";
    print "<button dojoType=\"dijit.form.Button\" onclick=\"editSelectedInstance()\">" . __('Edit') . "</button>";
    print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedInstances()\">" . __('Remove') . "</button>";
    print "</div>";
    #toolbar
    $result = db_query($link, "SELECT *,\n\t\t\t(SELECT COUNT(*) FROM ttrss_linked_feeds\n\t\t\t\tWHERE instance_id = ttrss_linked_instances.id) AS num_feeds\n\t\t\tFROM ttrss_linked_instances\n\t\t\tORDER BY {$sort}");
    print "<p class=\"insensitive\" style='margin-left : 1em;'>" . __("You can connect other instances of Tiny Tiny RSS to this one to share Popular feeds. Link to this instance of Tiny Tiny RSS by using this URL:");
    print " <a href=\"#\" onclick=\"alert('" . htmlspecialchars(get_self_url_prefix()) . "')\">(display url)</a>";
    print "<p><table width='100%' id='prefInstanceList' class='prefInstanceList' cellspacing='0'>";
    print "<tr class=\"title\">\n\t\t\t<td align='center' width=\"5%\">&nbsp;</td>\n\t\t\t<td width=''><a href=\"#\" onclick=\"updateInstanceList('access_url')\">" . __('Instance URL') . "</a></td>\n\t\t\t<td width='20%'><a href=\"#\" onclick=\"updateInstanceList('access_key')\">" . __('Access key') . "</a></td>\n\t\t\t<td width='10%'><a href=\"#\" onclick=\"updateUsersList('last_connected')\">" . __('Last connected') . "</a></td>\n\t\t\t<td width='10%'><a href=\"#\" onclick=\"updateUsersList('num_feeds')\">" . __('Stored feeds') . "</a></td>\n\t\t\t</tr>";
    $lnum = 0;
    while ($line = db_fetch_assoc($result)) {
        $class = $lnum % 2 ? "even" : "odd";
        $id = $line['id'];
        $this_row_id = "id=\"LIRR-{$id}\"";
        $line["last_connected"] = make_local_datetime($link, $line["last_connected"], false);
        print "<tr class=\"{$class}\" {$this_row_id}>";
        print "<td align='center'><input onclick='toggleSelectRow(this);'\n\t\t\t\ttype=\"checkbox\" id=\"LICHK-{$id}\"></td>";
        $onclick = "onclick='editInstance({$id}, event)' title='" . __('Click to edit') . "'";
        $access_key = mb_substr($line['access_key'], 0, 4) . '...' . mb_substr($line['access_key'], -4);
        print "<td {$onclick}>" . htmlspecialchars($line['access_url']) . "</td>";
        print "<td {$onclick}>" . htmlspecialchars($access_key) . "</td>";
        print "<td {$onclick}>" . htmlspecialchars($line['last_connected']) . "</td>";
        print "<td {$onclick}>" . htmlspecialchars($line['num_feeds']) . "</td>";
        print "</tr>";
        ++$lnum;
    }
    print "</table>";
    print "</div>";
    #pane
    print "</div>";
    #container
}
Beispiel #17
0
 private function format_headline_subtoolbar($feed_site_url, $feed_title, $feed_id, $is_cat, $search, $search_mode, $view_mode, $error, $feed_last_updated)
 {
     $catchup_sel_link = "catchupSelection()";
     $archive_sel_link = "archiveSelection()";
     $delete_sel_link = "deleteSelection()";
     $sel_all_link = "selectArticles('all')";
     $sel_unread_link = "selectArticles('unread')";
     $sel_none_link = "selectArticles('none')";
     $sel_inv_link = "selectArticles('invert')";
     $tog_unread_link = "selectionToggleUnread()";
     $tog_marked_link = "selectionToggleMarked()";
     $tog_published_link = "selectionTogglePublished()";
     $set_score_link = "setSelectionScore()";
     if ($is_cat) {
         $cat_q = "&is_cat={$is_cat}";
     }
     if ($search) {
         $search_q = "&q={$search}&smode={$search_mode}";
     } else {
         $search_q = "";
     }
     $reply .= "<span class=\"holder\">";
     $rss_link = htmlspecialchars(get_self_url_prefix() . "/public.php?op=rss&id={$feed_id}{$cat_q}{$search_q}");
     // right part
     $error_class = $error ? "error" : "";
     $reply .= "<span class='r'>\n\t\t\t<a href=\"#\"\n\t\t\t\ttitle=\"" . __("View as RSS feed") . "\"\n\t\t\t\tonclick=\"displayDlg('" . __("View as RSS") . "','generatedFeed', '{$feed_id}:{$is_cat}:{$rss_link}')\">\n\t\t\t\t<img class=\"noborder\" src=\"images/pub_set.png\"></a>";
     #		$reply .= "<span>";
     $reply .= "<span id='feed_title' class='{$error_class}'>";
     if ($feed_site_url) {
         $last_updated = T_sprintf("Last updated: %s", $feed_last_updated);
         $target = "target=\"_blank\"";
         $reply .= "<a title=\"{$last_updated}\" {$target} href=\"{$feed_site_url}\">" . truncate_string($feed_title, 30) . "</a>";
         if ($error) {
             $error = htmlspecialchars($error);
             $reply .= "&nbsp;<img title=\"{$error}\" src='images/error.png' alt='error' class=\"noborder\">";
         }
     } else {
         $reply .= $feed_title;
     }
     $reply .= "</span>";
     $reply .= "</span>";
     #		$reply .= "</span>";
     // left part
     $reply .= "<span class=\"main\">";
     $reply .= "<span id='selected_prompt'></span>";
     $reply .= "\n\t\t\t<a href=\"#\" onclick=\"{$sel_all_link}\">" . __('All') . "</a>,\n\t\t\t<a href=\"#\" onclick=\"{$sel_unread_link}\">" . __('Unread') . "</a>,\n\t\t\t<a href=\"#\" onclick=\"{$sel_inv_link}\">" . __('Invert') . "</a>,\n\t\t\t<a href=\"#\" onclick=\"{$sel_none_link}\">" . __('None') . "</a></li>";
     $reply .= " ";
     $reply .= "<select dojoType=\"dijit.form.Select\"\n\t\t\tonchange=\"headlineActionsChange(this)\">";
     $reply .= "<option value=\"false\">" . __('More...') . "</option>";
     $reply .= "<option value=\"0\" disabled=\"1\">" . __('Selection toggle:') . "</option>";
     $reply .= "<option value=\"{$tog_unread_link}\">" . __('Unread') . "</option>\n\t\t\t<option value=\"{$tog_marked_link}\">" . __('Starred') . "</option>\n\t\t\t<option value=\"{$tog_published_link}\">" . __('Published') . "</option>";
     $reply .= "<option value=\"0\" disabled=\"1\">" . __('Selection:') . "</option>";
     $reply .= "<option value=\"{$catchup_sel_link}\">" . __('Mark as read') . "</option>";
     $reply .= "<option value=\"{$set_score_link}\">" . __('Set score') . "</option>";
     if ($feed_id != "0") {
         $reply .= "<option value=\"{$archive_sel_link}\">" . __('Archive') . "</option>";
     } else {
         $reply .= "<option value=\"{$archive_sel_link}\">" . __('Move back') . "</option>";
         $reply .= "<option value=\"{$delete_sel_link}\">" . __('Delete') . "</option>";
     }
     if (PluginHost::getInstance()->get_plugin("mail")) {
         $reply .= "<option value=\"emailArticle(false)\">" . __('Forward by email') . "</option>";
     }
     if (PluginHost::getInstance()->get_plugin("mailto")) {
         $reply .= "<option value=\"mailtoArticle(false)\">" . __('Forward by email') . "</option>";
     }
     $reply .= "<option value=\"0\" disabled=\"1\">" . __('Feed:') . "</option>";
     //$reply .= "<option value=\"catchupPage()\">".__('Mark as read')."</option>";
     $reply .= "<option value=\"displayDlg('" . __("View as RSS") . "','generatedFeed', '{$feed_id}:{$is_cat}:{$rss_link}')\">" . __('View as RSS') . "</option>";
     $reply .= "</select>";
     //$reply .= "</h2";
     foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON) as $p) {
         $reply .= $p->hook_headline_toolbar_button($feed_id, $is_cat);
     }
     $reply .= "</span></span>";
     return $reply;
 }
Beispiel #18
0
function update_rss_feed($link, $feed, $ignore_daemon = false, $no_cache = false, $override_url = false)
{
    require_once "lib/simplepie/simplepie.inc";
    require_once "lib/magpierss/rss_fetch.inc";
    require_once 'lib/magpierss/rss_utils.inc';
    $debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
    if (!$_REQUEST["daemon"] && !$ignore_daemon) {
        return false;
    }
    if ($debug_enabled) {
        _debug("update_rss_feed: start");
    }
    if (!$ignore_daemon) {
        if (DB_TYPE == "pgsql") {
            $updstart_thresh_qpart = "(ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < NOW() - INTERVAL '120 seconds')";
        } else {
            $updstart_thresh_qpart = "(ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < DATE_SUB(NOW(), INTERVAL 120 SECOND))";
        }
        $result = db_query($link, "SELECT id,update_interval,auth_login,\n\t\t\t\tauth_pass,cache_images,update_method,last_updated\n\t\t\t\tFROM ttrss_feeds WHERE id = '{$feed}' AND {$updstart_thresh_qpart}");
    } else {
        $result = db_query($link, "SELECT id,update_interval,auth_login,\n\t\t\t\tfeed_url,auth_pass,cache_images,update_method,last_updated,\n\t\t\t\tmark_unread_on_update, owner_uid, update_on_checksum_change,\n\t\t\t\tpubsub_state\n\t\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
    }
    if (db_num_rows($result) == 0) {
        if ($debug_enabled) {
            _debug("update_rss_feed: feed {$feed} NOT FOUND/SKIPPED");
        }
        return false;
    }
    $update_method = db_fetch_result($result, 0, "update_method");
    $last_updated = db_fetch_result($result, 0, "last_updated");
    $owner_uid = db_fetch_result($result, 0, "owner_uid");
    $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
    $update_on_checksum_change = sql_bool_to_bool(db_fetch_result($result, 0, "update_on_checksum_change"));
    $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
    db_query($link, "UPDATE ttrss_feeds SET last_update_started = NOW()\n\t\t\tWHERE id = '{$feed}'");
    $auth_login = db_fetch_result($result, 0, "auth_login");
    $auth_pass = db_fetch_result($result, 0, "auth_pass");
    if ($update_method == 0) {
        $update_method = DEFAULT_UPDATE_METHOD + 1;
    }
    // 1 - Magpie
    // 2 - SimplePie
    // 3 - Twitter OAuth
    if ($update_method == 2) {
        $use_simplepie = true;
    } else {
        $use_simplepie = false;
    }
    if ($debug_enabled) {
        _debug("update method: {$update_method} (feed setting: {$update_method}) (use simplepie: {$use_simplepie})\n");
    }
    if ($update_method == 1) {
        $auth_login = urlencode($auth_login);
        $auth_pass = urlencode($auth_pass);
    }
    $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
    $fetch_url = db_fetch_result($result, 0, "feed_url");
    $feed = db_escape_string($feed);
    if ($auth_login && $auth_pass) {
        $url_parts = array();
        preg_match("/(^[^:]*):\\/\\/(.*)/", $fetch_url, $url_parts);
        if ($url_parts[1] && $url_parts[2]) {
            $fetch_url = $url_parts[1] . "://{$auth_login}:{$auth_pass}@" . $url_parts[2];
        }
    }
    if ($override_url) {
        $fetch_url = $override_url;
    }
    if ($debug_enabled) {
        _debug("update_rss_feed: fetching [{$fetch_url}]...");
    }
    // Ignore cache if new feed or manual update.
    $cache_age = is_null($last_updated) || $last_updated == '1970-01-01 00:00:00' ? -1 : get_feed_update_interval($link, $feed) * 60;
    if ($update_method == 3) {
        $rss = fetch_twitter_rss($link, $fetch_url, $owner_uid);
    } else {
        if ($update_method == 1) {
            define('MAGPIE_CACHE_AGE', $cache_age);
            define('MAGPIE_CACHE_ON', !$no_cache);
            define('MAGPIE_FETCH_TIME_OUT', 60);
            define('MAGPIE_CACHE_DIR', CACHE_DIR . "/magpie");
            $rss = @fetch_rss($fetch_url);
        } else {
            $simplepie_cache_dir = CACHE_DIR . "/simplepie";
            if (!is_dir($simplepie_cache_dir)) {
                mkdir($simplepie_cache_dir);
            }
            $rss = new SimplePie();
            $rss->set_useragent(SELF_USER_AGENT);
            #			$rss->set_timeout(10);
            $rss->set_feed_url($fetch_url);
            $rss->set_output_encoding('UTF-8');
            //$rss->force_feed(true);
            if ($debug_enabled) {
                _debug("feed update interval (sec): " . get_feed_update_interval($link, $feed) * 60);
            }
            $rss->enable_cache(!$no_cache);
            if (!$no_cache) {
                $rss->set_cache_location($simplepie_cache_dir);
                $rss->set_cache_duration($cache_age);
            }
            $rss->init();
        }
    }
    //		print_r($rss);
    if ($debug_enabled) {
        _debug("update_rss_feed: fetch done, parsing...");
    }
    $feed = db_escape_string($feed);
    if ($update_method == 2) {
        $fetch_ok = !$rss->error();
    } else {
        $fetch_ok = !!$rss;
    }
    if ($fetch_ok) {
        if ($debug_enabled) {
            _debug("update_rss_feed: processing feed data...");
        }
        //			db_query($link, "BEGIN");
        if (DB_TYPE == "pgsql") {
            $favicon_interval_qpart = "favicon_last_checked < NOW() - INTERVAL '12 hour'";
        } else {
            $favicon_interval_qpart = "favicon_last_checked < DATE_SUB(NOW(), INTERVAL 12 HOUR)";
        }
        $result = db_query($link, "SELECT title,icon_url,site_url,owner_uid,\n\t\t\t\t(favicon_last_checked IS NULL OR {$favicon_interval_qpart}) AS\n\t\t\t\t\t\tfavicon_needs_check\n\t\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
        $registered_title = db_fetch_result($result, 0, "title");
        $orig_icon_url = db_fetch_result($result, 0, "icon_url");
        $orig_site_url = db_fetch_result($result, 0, "site_url");
        $favicon_needs_check = sql_bool_to_bool(db_fetch_result($result, 0, "favicon_needs_check"));
        $owner_uid = db_fetch_result($result, 0, "owner_uid");
        if ($use_simplepie) {
            $site_url = db_escape_string(trim($rss->get_link()));
        } else {
            $site_url = db_escape_string(trim($rss->channel["link"]));
        }
        // weird, weird Magpie
        if (!$use_simplepie) {
            if (!$site_url) {
                $site_url = db_escape_string($rss->channel["link_"]);
            }
        }
        $site_url = rewrite_relative_url($fetch_url, $site_url);
        $site_url = substr($site_url, 0, 250);
        if ($debug_enabled) {
            _debug("update_rss_feed: checking favicon...");
        }
        if ($favicon_needs_check) {
            check_feed_favicon($site_url, $feed, $link);
            db_query($link, "UPDATE ttrss_feeds SET favicon_last_checked = NOW()\n\t\t\t\t\tWHERE id = '{$feed}'");
        }
        if (!$registered_title || $registered_title == "[Unknown]") {
            if ($use_simplepie) {
                $feed_title = db_escape_string($rss->get_title());
            } else {
                $feed_title = db_escape_string($rss->channel["title"]);
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: registering title: {$feed_title}");
            }
            db_query($link, "UPDATE ttrss_feeds SET\n\t\t\t\t\ttitle = '{$feed_title}' WHERE id = '{$feed}'");
        }
        if ($site_url && $orig_site_url != $site_url) {
            db_query($link, "UPDATE ttrss_feeds SET\n\t\t\t\t\tsite_url = '{$site_url}' WHERE id = '{$feed}'");
        }
        //			print "I: " . $rss->channel["image"]["url"];
        if (!$use_simplepie) {
            $icon_url = db_escape_string(trim($rss->image["url"]));
        } else {
            $icon_url = db_escape_string(trim($rss->get_image_url()));
        }
        $icon_url = rewrite_relative_url($fetch_url, $icon_url);
        $icon_url = substr($icon_url, 0, 250);
        if ($icon_url && $orig_icon_url != $icon_url) {
            db_query($link, "UPDATE ttrss_feeds SET icon_url = '{$icon_url}' WHERE id = '{$feed}'");
        }
        if ($debug_enabled) {
            _debug("update_rss_feed: loading filters...");
        }
        $filters = load_filters($link, $feed, $owner_uid);
        //			if ($debug_enabled) {
        //				print_r($filters);
        //			}
        if ($use_simplepie) {
            $iterator = $rss->get_items();
        } else {
            $iterator = $rss->items;
            if (!$iterator || !is_array($iterator)) {
                $iterator = $rss->entries;
            }
            if (!$iterator || !is_array($iterator)) {
                $iterator = $rss;
            }
        }
        if (!is_array($iterator)) {
            /* db_query($link, "UPDATE ttrss_feeds
            			SET last_error = 'Parse error: can\'t find any articles.'
            			WHERE id = '$feed'"); */
            // clear any errors and mark feed as updated if fetched okay
            // even if it's blank
            if ($debug_enabled) {
                _debug("update_rss_feed: entry iterator is not an array, no articles?");
            }
            db_query($link, "UPDATE ttrss_feeds\n\t\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
            return;
            // no articles
        }
        if ($pubsub_state != 2 && PUBSUBHUBBUB_ENABLED) {
            if ($debug_enabled) {
                _debug("update_rss_feed: checking for PUSH hub...");
            }
            $feed_hub_url = false;
            if ($use_simplepie) {
                $links = $rss->get_links('hub');
                if ($links && is_array($links)) {
                    foreach ($links as $l) {
                        $feed_hub_url = $l;
                        break;
                    }
                }
            } else {
                $atom = $rss->channel['atom'];
                if ($atom) {
                    if ($atom['link@rel'] == 'hub') {
                        $feed_hub_url = $atom['link@href'];
                    }
                    if (!$feed_hub_url && $atom['link#'] > 1) {
                        for ($i = 2; $i <= $atom['link#']; $i++) {
                            if ($atom["link#{$i}@rel"] == 'hub') {
                                $feed_hub_url = $atom["link#{$i}@href"];
                                break;
                            }
                        }
                    }
                } else {
                    $feed_hub_url = $rss->channel['link_hub'];
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: feed hub url: {$feed_hub_url}");
            }
            if ($feed_hub_url && function_exists('curl_init') && !ini_get("open_basedir")) {
                require_once 'lib/pubsubhubbub/subscriber.php';
                $callback_url = get_self_url_prefix() . "/public.php?op=pubsub&id={$feed}";
                $s = new Subscriber($feed_hub_url, $callback_url);
                $rc = $s->subscribe($fetch_url);
                if ($debug_enabled) {
                    _debug("update_rss_feed: feed hub url found, subscribe request sent.");
                }
                db_query($link, "UPDATE ttrss_feeds SET pubsub_state = 1\n\t\t\t\t\t\tWHERE id = '{$feed}'");
            }
        }
        if ($debug_enabled) {
            _debug("update_rss_feed: processing articles...");
        }
        foreach ($iterator as $item) {
            if ($_REQUEST['xdebug'] == 2) {
                print_r($item);
            }
            if ($use_simplepie) {
                $entry_guid = $item->get_id();
                if (!$entry_guid) {
                    $entry_guid = $item->get_link();
                }
                if (!$entry_guid) {
                    $entry_guid = make_guid_from_title($item->get_title());
                }
            } else {
                $entry_guid = $item["id"];
                if (!$entry_guid) {
                    $entry_guid = $item["guid"];
                }
                if (!$entry_guid) {
                    $entry_guid = $item["about"];
                }
                if (!$entry_guid) {
                    $entry_guid = $item["link"];
                }
                if (!$entry_guid) {
                    $entry_guid = make_guid_from_title($item["title"]);
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: guid {$entry_guid}");
            }
            if (!$entry_guid) {
                continue;
            }
            $entry_timestamp = "";
            if ($use_simplepie) {
                $entry_timestamp = strtotime($item->get_date());
            } else {
                $rss_2_date = $item['pubdate'];
                $rss_1_date = $item['dc']['date'];
                $atom_date = $item['issued'];
                if (!$atom_date) {
                    $atom_date = $item['updated'];
                }
                if ($atom_date != "") {
                    $entry_timestamp = parse_w3cdtf($atom_date);
                }
                if ($rss_1_date != "") {
                    $entry_timestamp = parse_w3cdtf($rss_1_date);
                }
                if ($rss_2_date != "") {
                    $entry_timestamp = strtotime($rss_2_date);
                }
            }
            if ($entry_timestamp == "" || $entry_timestamp == -1 || !$entry_timestamp) {
                $entry_timestamp = time();
                $no_orig_date = 'true';
            } else {
                $no_orig_date = 'false';
            }
            $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
            if ($debug_enabled) {
                _debug("update_rss_feed: date {$entry_timestamp} [{$entry_timestamp_fmt}]");
            }
            if ($use_simplepie) {
                $entry_title = $item->get_title();
            } else {
                $entry_title = trim(strip_tags($item["title"]));
            }
            if ($use_simplepie) {
                $entry_link = $item->get_link();
            } else {
                // strange Magpie workaround
                $entry_link = $item["link_"];
                if (!$entry_link) {
                    $entry_link = $item["link"];
                }
            }
            $entry_link = rewrite_relative_url($site_url, $entry_link);
            if ($debug_enabled) {
                _debug("update_rss_feed: title {$entry_title}");
                _debug("update_rss_feed: link {$entry_link}");
            }
            if (!$entry_title) {
                $entry_title = date("Y-m-d H:i:s", $entry_timestamp);
            }
            $entry_link = strip_tags($entry_link);
            if ($use_simplepie) {
                $entry_content = $item->get_content();
                if (!$entry_content) {
                    $entry_content = $item->get_description();
                }
            } else {
                $entry_content = $item["content:escaped"];
                if (!$entry_content) {
                    $entry_content = $item["content:encoded"];
                }
                if (!$entry_content && is_array($entry_content)) {
                    $entry_content = $item["content"]["encoded"];
                }
                if (!$entry_content) {
                    $entry_content = $item["content"];
                }
                if (is_array($entry_content)) {
                    $entry_content = $entry_content[0];
                }
                // Magpie bugs are getting ridiculous
                if (trim($entry_content) == "Array") {
                    $entry_content = false;
                }
                if (!$entry_content) {
                    $entry_content = $item["atom_content"];
                }
                if (!$entry_content) {
                    $entry_content = $item["summary"];
                }
                if (!$entry_content || strlen($entry_content) < strlen($item["description"])) {
                    $entry_content = $item["description"];
                }
                // WTF
                if (is_array($entry_content)) {
                    $entry_content = $entry_content["encoded"];
                    if (!$entry_content) {
                        $entry_content = $entry_content["escaped"];
                    }
                }
            }
            if ($cache_images && is_writable(CACHE_DIR . '/images')) {
                $entry_content = cache_images($entry_content, $site_url, $debug_enabled);
            }
            if ($_REQUEST["xdebug"] == 2) {
                print "update_rss_feed: content: ";
                print $entry_content;
                print "\n";
            }
            $entry_content_unescaped = $entry_content;
            if ($use_simplepie) {
                $entry_comments = strip_tags($item->data["comments"]);
                if ($item->get_author()) {
                    $entry_author_item = $item->get_author();
                    $entry_author = $entry_author_item->get_name();
                    if (!$entry_author) {
                        $entry_author = $entry_author_item->get_email();
                    }
                    $entry_author = db_escape_string($entry_author);
                }
            } else {
                $entry_comments = strip_tags($item["comments"]);
                $entry_author = db_escape_string(strip_tags($item['dc']['creator']));
                if ($item['author']) {
                    if (is_array($item['author'])) {
                        if (!$entry_author) {
                            $entry_author = db_escape_string(strip_tags($item['author']['name']));
                        }
                        if (!$entry_author) {
                            $entry_author = db_escape_string(strip_tags($item['author']['email']));
                        }
                    }
                    if (!$entry_author) {
                        $entry_author = db_escape_string(strip_tags($item['author']));
                    }
                }
            }
            if (preg_match('/^[\\t\\n\\r ]*$/', $entry_author)) {
                $entry_author = '';
            }
            $entry_guid = db_escape_string(strip_tags($entry_guid));
            $entry_guid = mb_substr($entry_guid, 0, 250);
            $result = db_query($link, "SELECT id FROM\tttrss_entries\n\t\t\t\t\tWHERE guid = '{$entry_guid}'");
            $entry_content = db_escape_string($entry_content, false);
            $content_hash = "SHA1:" . sha1(strip_tags($entry_content));
            $entry_title = db_escape_string($entry_title);
            $entry_link = db_escape_string($entry_link);
            $entry_comments = mb_substr(db_escape_string($entry_comments), 0, 250);
            $entry_author = mb_substr($entry_author, 0, 250);
            if ($use_simplepie) {
                $num_comments = 0;
                #FIXME#
            } else {
                $num_comments = db_escape_string($item["slash"]["comments"]);
            }
            if (!$num_comments) {
                $num_comments = 0;
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: looking for tags [1]...");
            }
            // parse <category> entries into tags
            $additional_tags = array();
            if ($use_simplepie) {
                $additional_tags_src = $item->get_categories();
                if (is_array($additional_tags_src)) {
                    foreach ($additional_tags_src as $tobj) {
                        array_push($additional_tags, $tobj->get_term());
                    }
                }
                if ($debug_enabled) {
                    _debug("update_rss_feed: category tags:");
                    print_r($additional_tags);
                }
            } else {
                $t_ctr = $item['category#'];
                if ($t_ctr == 0) {
                    $additional_tags = array();
                } else {
                    if ($t_ctr > 0) {
                        $additional_tags = array($item['category']);
                        if ($item['category@term']) {
                            array_push($additional_tags, $item['category@term']);
                        }
                        for ($i = 0; $i <= $t_ctr; $i++) {
                            if ($item["category#{$i}"]) {
                                array_push($additional_tags, $item["category#{$i}"]);
                            }
                            if ($item["category#{$i}@term"]) {
                                array_push($additional_tags, $item["category#{$i}@term"]);
                            }
                        }
                    }
                }
                // parse <dc:subject> elements
                $t_ctr = $item['dc']['subject#'];
                if ($t_ctr > 0) {
                    array_push($additional_tags, $item['dc']['subject']);
                    for ($i = 0; $i <= $t_ctr; $i++) {
                        if ($item['dc']["subject#{$i}"]) {
                            array_push($additional_tags, $item['dc']["subject#{$i}"]);
                        }
                    }
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: looking for tags [2]...");
            }
            /* taaaags */
            // <a href="..." rel="tag">Xorg</a>, //
            $entry_tags = null;
            preg_match_all("/<a.*?rel=['\"]tag['\"].*?\\>([^<]+)<\\/a>/i", $entry_content_unescaped, $entry_tags);
            $entry_tags = $entry_tags[1];
            $entry_tags = array_merge($entry_tags, $additional_tags);
            $entry_tags = array_unique($entry_tags);
            for ($i = 0; $i < count($entry_tags); $i++) {
                $entry_tags[$i] = mb_strtolower($entry_tags[$i], 'utf-8');
            }
            if ($debug_enabled) {
                //_debug("update_rss_feed: unfiltered tags found:");
                //print_r($entry_tags);
            }
            # sanitize content
            $entry_content = sanitize_article_content($entry_content);
            $entry_title = sanitize_article_content($entry_title);
            if ($debug_enabled) {
                _debug("update_rss_feed: done collecting data [TITLE:{$entry_title}]");
            }
            db_query($link, "BEGIN");
            if (db_num_rows($result) == 0) {
                if ($debug_enabled) {
                    _debug("update_rss_feed: base guid not found");
                }
                // base post entry does not exist, create it
                $result = db_query($link, "INSERT INTO ttrss_entries\n\t\t\t\t\t\t\t(title,\n\t\t\t\t\t\t\tguid,\n\t\t\t\t\t\t\tlink,\n\t\t\t\t\t\t\tupdated,\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tcontent_hash,\n\t\t\t\t\t\t\tno_orig_date,\n\t\t\t\t\t\t\tdate_updated,\n\t\t\t\t\t\t\tdate_entered,\n\t\t\t\t\t\t\tcomments,\n\t\t\t\t\t\t\tnum_comments,\n\t\t\t\t\t\t\tauthor)\n\t\t\t\t\t\tVALUES\n\t\t\t\t\t\t\t('{$entry_title}',\n\t\t\t\t\t\t\t'{$entry_guid}',\n\t\t\t\t\t\t\t'{$entry_link}',\n\t\t\t\t\t\t\t'{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t'{$entry_content}',\n\t\t\t\t\t\t\t'{$content_hash}',\n\t\t\t\t\t\t\t{$no_orig_date},\n\t\t\t\t\t\t\tNOW(),\n\t\t\t\t\t\t\tNOW(),\n\t\t\t\t\t\t\t'{$entry_comments}',\n\t\t\t\t\t\t\t'{$num_comments}',\n\t\t\t\t\t\t\t'{$entry_author}')");
            } else {
                // we keep encountering the entry in feeds, so we need to
                // update date_updated column so that we don't get horrible
                // dupes when the entry gets purged and reinserted again e.g.
                // in the case of SLOW SLOW OMG SLOW updating feeds
                $base_entry_id = db_fetch_result($result, 0, "id");
                db_query($link, "UPDATE ttrss_entries SET date_updated = NOW()\n\t\t\t\t\t\tWHERE id = '{$base_entry_id}'");
            }
            // now it should exist, if not - bad luck then
            $result = db_query($link, "SELECT\n\t\t\t\t\t\tid,content_hash,no_orig_date,title,\n\t\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(date_updated,1,19) as date_updated,\n\t\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(updated,1,19) as updated,\n\t\t\t\t\t\tnum_comments\n\t\t\t\t\tFROM\n\t\t\t\t\t\tttrss_entries\n\t\t\t\t\tWHERE guid = '{$entry_guid}'");
            $entry_ref_id = 0;
            $entry_int_id = 0;
            if (db_num_rows($result) == 1) {
                if ($debug_enabled) {
                    _debug("update_rss_feed: base guid found, checking for user record");
                }
                // this will be used below in update handler
                $orig_content_hash = db_fetch_result($result, 0, "content_hash");
                $orig_title = db_fetch_result($result, 0, "title");
                $orig_num_comments = db_fetch_result($result, 0, "num_comments");
                $orig_date_updated = strtotime(db_fetch_result($result, 0, "date_updated"));
                $ref_id = db_fetch_result($result, 0, "id");
                $entry_ref_id = $ref_id;
                // check for user post link to main table
                // do we allow duplicate posts with same GUID in different feeds?
                if (get_pref($link, "ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
                    $dupcheck_qpart = "AND (feed_id = '{$feed}' OR feed_id IS NULL)";
                } else {
                    $dupcheck_qpart = "";
                }
                /* Collect article tags here so we could filter by them: */
                $article_filters = get_article_filters($filters, $entry_title, $entry_content, $entry_link, $entry_timestamp, $entry_author, $entry_tags);
                if ($debug_enabled) {
                    _debug("update_rss_feed: article filters: ");
                    if (count($article_filters) != 0) {
                        print_r($article_filters);
                    }
                }
                if (find_article_filter($article_filters, "filter")) {
                    db_query($link, "COMMIT");
                    // close transaction in progress
                    continue;
                }
                $score = calculate_article_score($article_filters);
                if ($debug_enabled) {
                    _debug("update_rss_feed: initial score: {$score}");
                }
                $query = "SELECT ref_id, int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}'\n\t\t\t\t\t\t\t{$dupcheck_qpart}";
                //					if ($_REQUEST["xdebug"]) print "$query\n";
                $result = db_query($link, $query);
                // okay it doesn't exist - create user entry
                if (db_num_rows($result) == 0) {
                    if ($debug_enabled) {
                        _debug("update_rss_feed: user record not found, creating...");
                    }
                    if ($score >= -500 && !find_article_filter($article_filters, 'catchup')) {
                        $unread = 'true';
                        $last_read_qpart = 'NULL';
                    } else {
                        $unread = 'false';
                        $last_read_qpart = 'NOW()';
                    }
                    if (find_article_filter($article_filters, 'mark') || $score > 1000) {
                        $marked = 'true';
                    } else {
                        $marked = 'false';
                    }
                    if (find_article_filter($article_filters, 'publish')) {
                        $published = 'true';
                    } else {
                        $published = 'false';
                    }
                    // N-grams
                    if (DB_TYPE == "pgsql" and defined('_NGRAM_TITLE_DUPLICATE_THRESHOLD')) {
                        $result = db_query($link, "SELECT COUNT(*) AS similar FROM\n\t\t\t\t\t\t\t\t\tttrss_entries,ttrss_user_entries\n\t\t\t\t\t\t\t\tWHERE ref_id = id AND updated >= NOW() - INTERVAL '7 day'\n\t\t\t\t\t\t\t\t\tAND similarity(title, '{$entry_title}') >= " . _NGRAM_TITLE_DUPLICATE_THRESHOLD . "\n\t\t\t\t\t\t\t\t\tAND owner_uid = {$owner_uid}");
                        $ngram_similar = db_fetch_result($result, 0, "similar");
                        if ($debug_enabled) {
                            _debug("update_rss_feed: N-gram similar results: {$ngram_similar}");
                        }
                        if ($ngram_similar > 0) {
                            $unread = 'false';
                        }
                    }
                    $result = db_query($link, "INSERT INTO ttrss_user_entries\n\t\t\t\t\t\t\t\t(ref_id, owner_uid, feed_id, unread, last_read, marked,\n\t\t\t\t\t\t\t\t\tpublished, score, tag_cache, label_cache, uuid)\n\t\t\t\t\t\t\tVALUES ('{$ref_id}', '{$owner_uid}', '{$feed}', {$unread},\n\t\t\t\t\t\t\t\t{$last_read_qpart}, {$marked}, {$published}, '{$score}', '', '', '')");
                    if (PUBSUBHUBBUB_HUB && $published == 'true') {
                        $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key($link, -2, false, $owner_uid);
                        $p = new Publisher(PUBSUBHUBBUB_HUB);
                        $pubsub_result = $p->publish_update($rss_link);
                    }
                    $result = db_query($link, "SELECT int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}' AND\n\t\t\t\t\t\t\t\tfeed_id = '{$feed}' LIMIT 1");
                    if (db_num_rows($result) == 1) {
                        $entry_int_id = db_fetch_result($result, 0, "int_id");
                    }
                } else {
                    if ($debug_enabled) {
                        _debug("update_rss_feed: user record FOUND");
                    }
                    $entry_ref_id = db_fetch_result($result, 0, "ref_id");
                    $entry_int_id = db_fetch_result($result, 0, "int_id");
                }
                if ($debug_enabled) {
                    _debug("update_rss_feed: RID: {$entry_ref_id}, IID: {$entry_int_id}");
                }
                $post_needs_update = false;
                $update_insignificant = false;
                if ($orig_num_comments != $num_comments) {
                    $post_needs_update = true;
                    $update_insignificant = true;
                }
                if ($content_hash != $orig_content_hash) {
                    $post_needs_update = true;
                    $update_insignificant = false;
                }
                if (db_escape_string($orig_title) != $entry_title) {
                    $post_needs_update = true;
                    $update_insignificant = false;
                }
                // if post needs update, update it and mark all user entries
                // linking to this post as updated
                if ($post_needs_update) {
                    if (defined('DAEMON_EXTENDED_DEBUG')) {
                        _debug("update_rss_feed: post {$entry_guid} needs update...");
                    }
                    //						print "<!-- post $orig_title needs update : $post_needs_update -->";
                    db_query($link, "UPDATE ttrss_entries\n\t\t\t\t\t\t\tSET title = '{$entry_title}', content = '{$entry_content}',\n\t\t\t\t\t\t\t\tcontent_hash = '{$content_hash}',\n\t\t\t\t\t\t\t\tupdated = '{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t\tnum_comments = '{$num_comments}'\n\t\t\t\t\t\t\tWHERE id = '{$ref_id}'");
                    if (!$update_insignificant) {
                        if ($mark_unread_on_update) {
                            db_query($link, "UPDATE ttrss_user_entries\n\t\t\t\t\t\t\t\t\tSET last_read = null, unread = true WHERE ref_id = '{$ref_id}'");
                        } else {
                            if ($update_on_checksum_change) {
                                db_query($link, "UPDATE ttrss_user_entries\n\t\t\t\t\t\t\t\t\tSET last_read = null WHERE ref_id = '{$ref_id}'\n\t\t\t\t\t\t\t\t\t\tAND unread = false");
                            }
                        }
                    }
                }
            }
            db_query($link, "COMMIT");
            if ($debug_enabled) {
                _debug("update_rss_feed: assigning labels...");
            }
            assign_article_to_labels($link, $entry_ref_id, $article_filters, $owner_uid);
            if ($debug_enabled) {
                _debug("update_rss_feed: looking for enclosures...");
            }
            // enclosures
            $enclosures = array();
            if ($use_simplepie) {
                $encs = $item->get_enclosures();
                if (is_array($encs)) {
                    foreach ($encs as $e) {
                        $e_item = array($e->link, $e->type, $e->length);
                        array_push($enclosures, $e_item);
                    }
                }
            } else {
                // <enclosure>
                $e_ctr = $item['enclosure#'];
                if ($e_ctr > 0) {
                    $e_item = array($item['enclosure@url'], $item['enclosure@type'], $item['enclosure@length']);
                    array_push($enclosures, $e_item);
                    for ($i = 0; $i <= $e_ctr; $i++) {
                        if ($item["enclosure#{$i}@url"]) {
                            $e_item = array($item["enclosure#{$i}@url"], $item["enclosure#{$i}@type"], $item["enclosure#{$i}@length"]);
                            array_push($enclosures, $e_item);
                        }
                    }
                }
                // <media:content>
                // can there be many of those? yes -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);
                    for ($i = 0; $i <= $m_ctr; $i++) {
                        if ($item["media"]["content#{$i}@url"]) {
                            $e_item = array($item["media"]["content#{$i}@url"], $item["media"]["content#{$i}@medium"], $item["media"]["content#{$i}@length"]);
                            array_push($enclosures, $e_item);
                        }
                    }
                }
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: article enclosures:");
                print_r($enclosures);
            }
            db_query($link, "BEGIN");
            foreach ($enclosures as $enc) {
                $enc_url = db_escape_string($enc[0]);
                $enc_type = db_escape_string($enc[1]);
                $enc_dur = db_escape_string($enc[2]);
                $result = db_query($link, "SELECT id FROM ttrss_enclosures\n\t\t\t\t\t\tWHERE content_url = '{$enc_url}' AND post_id = '{$entry_ref_id}'");
                if (db_num_rows($result) == 0) {
                    db_query($link, "INSERT INTO ttrss_enclosures\n\t\t\t\t\t\t\t(content_url, content_type, title, duration, post_id) VALUES\n\t\t\t\t\t\t\t('{$enc_url}', '{$enc_type}', '', '{$enc_dur}', '{$entry_ref_id}')");
                }
            }
            db_query($link, "COMMIT");
            // check for manual tags (we have to do it here since they're loaded from filters)
            foreach ($article_filters as $f) {
                if ($f["type"] == "tag") {
                    $manual_tags = trim_array(explode(",", $f["param"]));
                    foreach ($manual_tags as $tag) {
                        if (tag_is_valid($tag)) {
                            array_push($entry_tags, $tag);
                        }
                    }
                }
            }
            // Skip boring tags
            $boring_tags = trim_array(explode(",", mb_strtolower(get_pref($link, 'BLACKLISTED_TAGS', $owner_uid, ''), 'utf-8')));
            $filtered_tags = array();
            $tags_to_cache = array();
            if ($entry_tags && is_array($entry_tags)) {
                foreach ($entry_tags as $tag) {
                    if (array_search($tag, $boring_tags) === false) {
                        array_push($filtered_tags, $tag);
                    }
                }
            }
            $filtered_tags = array_unique($filtered_tags);
            if ($debug_enabled) {
                _debug("update_rss_feed: filtered article tags:");
                print_r($filtered_tags);
            }
            // Save article tags in the database
            if (count($filtered_tags) > 0) {
                db_query($link, "BEGIN");
                foreach ($filtered_tags as $tag) {
                    $tag = sanitize_tag($tag);
                    $tag = db_escape_string($tag);
                    if (!tag_is_valid($tag)) {
                        continue;
                    }
                    $result = db_query($link, "SELECT id FROM ttrss_tags\n\t\t\t\t\t\t\tWHERE tag_name = '{$tag}' AND post_int_id = '{$entry_int_id}' AND\n\t\t\t\t\t\t\towner_uid = '{$owner_uid}' LIMIT 1");
                    if ($result && db_num_rows($result) == 0) {
                        db_query($link, "INSERT INTO ttrss_tags\n\t\t\t\t\t\t\t\t\t(owner_uid,tag_name,post_int_id)\n\t\t\t\t\t\t\t\t\tVALUES ('{$owner_uid}','{$tag}', '{$entry_int_id}')");
                    }
                    array_push($tags_to_cache, $tag);
                }
                /* update the cache */
                $tags_to_cache = array_unique($tags_to_cache);
                $tags_str = db_escape_string(join(",", $tags_to_cache));
                db_query($link, "UPDATE ttrss_user_entries\n\t\t\t\t\t\tSET tag_cache = '{$tags_str}' WHERE ref_id = '{$entry_ref_id}'\n\t\t\t\t\t\tAND owner_uid = {$owner_uid}");
                db_query($link, "COMMIT");
            }
            if ($debug_enabled) {
                _debug("update_rss_feed: article processed");
            }
        }
        if (!$last_updated) {
            if ($debug_enabled) {
                _debug("update_rss_feed: new feed, catching it up...");
            }
            catchup_feed($link, $feed, false, $owner_uid);
        }
        if ($debug_enabled) {
            _debug("purging feed...");
        }
        purge_feed($link, $feed, 0, $debug_enabled);
        db_query($link, "UPDATE ttrss_feeds\n\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
        //			db_query($link, "COMMIT");
    } else {
        if ($use_simplepie) {
            $error_msg = mb_substr($rss->error(), 0, 250);
        } else {
            $error_msg = mb_substr(magpie_error(), 0, 250);
        }
        if ($debug_enabled) {
            _debug("update_rss_feed: error fetching feed: {$error_msg}");
        }
        $error_msg = db_escape_string($error_msg);
        db_query($link, "UPDATE ttrss_feeds SET last_error = '{$error_msg}',\n\t\t\t\t\tlast_updated = NOW() WHERE id = '{$feed}'");
    }
    if ($use_simplepie) {
        unset($rss);
    }
    if ($debug_enabled) {
        _debug("update_rss_feed: done");
    }
}
Beispiel #19
0
 function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes, $article_id)
 {
     $xpath = new DOMXpath($doc);
     if ($article_id) {
         $entries = $xpath->query('(//img[@src])|(//video/source[@src])');
         foreach ($entries as $entry) {
             if ($entry->hasAttribute('src')) {
                 $src = rewrite_relative_url($site_url, $entry->getAttribute('src'));
                 $extension = $entry->tagName == 'source' ? '.mp4' : '.png';
                 $local_filename = $this->cache_dir . $article_id . "-" . sha1($src) . $extension;
                 if (file_exists($local_filename)) {
                     $entry->setAttribute("src", get_self_url_prefix() . "/public.php?op=cache_starred_images_getimage&method=image&hash=" . $article_id . "-" . sha1($src) . $extension);
                 }
             }
         }
     }
     return $doc;
 }
 static function opml_publish_url($link)
 {
     $url_path = get_self_url_prefix();
     $url_path .= "/opml.php?op=publish&key=" . get_feed_access_key($link, 'OPML:Publish', false, $_SESSION["uid"]);
     return $url_path;
 }
 private function publishArticlesById($link, $ids, $cmode)
 {
     $tmp_ids = array();
     foreach ($ids as $id) {
         array_push($tmp_ids, "ref_id = '{$id}'");
     }
     $ids_qpart = join(" OR ", $tmp_ids);
     if ($cmode == 0) {
         db_query($link, "UPDATE ttrss_user_entries SET\n\t\t\tpublished = false,last_read = NOW()\n\t\t\tWHERE ({$ids_qpart}) AND owner_uid = " . $_SESSION["uid"]);
     } else {
         if ($cmode == 1) {
             db_query($link, "UPDATE ttrss_user_entries SET\n\t\t\tpublished = true,last_read = NOW()\n\t\t\tWHERE ({$ids_qpart}) AND owner_uid = " . $_SESSION["uid"]);
         } else {
             db_query($link, "UPDATE ttrss_user_entries SET\n\t\t\tpublished = NOT published,last_read = NOW()\n\t\t\tWHERE ({$ids_qpart}) AND owner_uid = " . $_SESSION["uid"]);
         }
     }
     if (PUBSUBHUBBUB_HUB) {
         $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key($link, -2, false);
         $p = new Publisher(PUBSUBHUBBUB_HUB);
         $pubsub_result = $p->publish_update($rss_link);
     }
 }
function update_rss_feed($feed, $ignore_daemon = false, $no_cache = false)
{
    $debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
    _debug("start", $debug_enabled);
    $result = db_query("SELECT id,update_interval,auth_login,\n\t\t\tfeed_url,auth_pass,cache_images,last_updated,\n\t\t\tmark_unread_on_update, owner_uid,\n\t\t\tpubsub_state, auth_pass_encrypted,\n\t\t\t(SELECT max(date_entered) FROM\n\t\t\t\tttrss_entries, ttrss_user_entries where ref_id = id AND feed_id = '{$feed}') AS last_article_timestamp\n\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
    if (db_num_rows($result) == 0) {
        _debug("feed {$feed} NOT FOUND/SKIPPED", $debug_enabled);
        return false;
    }
    $last_updated = db_fetch_result($result, 0, "last_updated");
    $last_article_timestamp = @strtotime(db_fetch_result($result, 0, "last_article_timestamp"));
    if (defined('_DISABLE_HTTP_304')) {
        $last_article_timestamp = 0;
    }
    $owner_uid = db_fetch_result($result, 0, "owner_uid");
    $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
    $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
    $auth_pass_encrypted = sql_bool_to_bool(db_fetch_result($result, 0, "auth_pass_encrypted"));
    db_query("UPDATE ttrss_feeds SET last_update_started = NOW()\n\t\t\tWHERE id = '{$feed}'");
    $auth_login = db_fetch_result($result, 0, "auth_login");
    $auth_pass = db_fetch_result($result, 0, "auth_pass");
    if ($auth_pass_encrypted) {
        require_once "crypt.php";
        $auth_pass = decrypt_string($auth_pass);
    }
    $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
    $fetch_url = db_fetch_result($result, 0, "feed_url");
    $feed = db_escape_string($feed);
    $date_feed_processed = date('Y-m-d H:i');
    $cache_filename = CACHE_DIR . "/simplepie/" . sha1($fetch_url) . ".xml";
    $pluginhost = new PluginHost();
    $pluginhost->set_debug($debug_enabled);
    $user_plugins = get_pref("_ENABLED_PLUGINS", $owner_uid);
    $pluginhost->load(PLUGINS, PluginHost::KIND_ALL);
    $pluginhost->load($user_plugins, PluginHost::KIND_USER, $owner_uid);
    $pluginhost->load_data();
    $rss = false;
    $rss_hash = false;
    $force_refetch = isset($_REQUEST["force_refetch"]);
    if (file_exists($cache_filename) && is_readable($cache_filename) && !$auth_login && !$auth_pass && filemtime($cache_filename) > time() - 30) {
        _debug("using local cache.", $debug_enabled);
        @($feed_data = file_get_contents($cache_filename));
        if ($feed_data) {
            $rss_hash = sha1($feed_data);
        }
    } else {
        _debug("local cache will not be used for this feed", $debug_enabled);
    }
    if (!$rss) {
        foreach ($pluginhost->get_hooks(PluginHost::HOOK_FETCH_FEED) as $plugin) {
            $feed_data = $plugin->hook_fetch_feed($feed_data, $fetch_url, $owner_uid, $feed);
        }
        if (!$feed_data) {
            _debug("fetching [{$fetch_url}]...", $debug_enabled);
            _debug("If-Modified-Since: " . gmdate('D, d M Y H:i:s \\G\\M\\T', $last_article_timestamp), $debug_enabled);
            $feed_data = fetch_file_contents($fetch_url, false, $auth_login, $auth_pass, false, $no_cache ? FEED_FETCH_NO_CACHE_TIMEOUT : FEED_FETCH_TIMEOUT, $force_refetch ? 0 : $last_article_timestamp);
            global $fetch_curl_used;
            if (!$fetch_curl_used) {
                $tmp = @gzdecode($feed_data);
                if ($tmp) {
                    $feed_data = $tmp;
                }
            }
            $feed_data = trim($feed_data);
            _debug("fetch done.", $debug_enabled);
            /* if ($feed_data) {
            					$error = verify_feed_xml($feed_data);
            
            					if ($error) {
            						_debug("error verifying XML, code: " . $error->code, $debug_enabled);
            
            						if ($error->code == 26) {
            							_debug("got error 26, trying to decode entities...", $debug_enabled);
            
            							$feed_data = html_entity_decode($feed_data, ENT_COMPAT, 'UTF-8');
            
            							$error = verify_feed_xml($feed_data);
            
            							if ($error) $feed_data = '';
            						}
            					}
            				} */
        }
        if (!$feed_data) {
            global $fetch_last_error;
            global $fetch_last_error_code;
            _debug("unable to fetch: {$fetch_last_error} [{$fetch_last_error_code}]", $debug_enabled);
            $error_escaped = '';
            // If-Modified-Since
            if ($fetch_last_error_code != 304) {
                $error_escaped = db_escape_string($fetch_last_error);
            } else {
                _debug("source claims data not modified, nothing to do.", $debug_enabled);
            }
            db_query("UPDATE ttrss_feeds SET last_error = '{$error_escaped}',\n\t\t\t\t\t\tlast_updated = NOW() WHERE id = '{$feed}'");
            return;
        }
    }
    foreach ($pluginhost->get_hooks(PluginHost::HOOK_FEED_FETCHED) as $plugin) {
        $feed_data = $plugin->hook_feed_fetched($feed_data, $fetch_url, $owner_uid, $feed);
    }
    // set last update to now so if anything *simplepie* crashes later we won't be
    // continuously failing on the same feed
    //db_query("UPDATE ttrss_feeds SET last_updated = NOW() WHERE id = '$feed'");
    if (!$rss) {
        $rss = new FeedParser($feed_data);
        $rss->init();
    }
    //		print_r($rss);
    $feed = db_escape_string($feed);
    if (!$rss->error()) {
        // cache data for later
        if (!$auth_pass && !$auth_login && is_writable(CACHE_DIR . "/simplepie")) {
            $new_rss_hash = sha1($rss_data);
            if ($new_rss_hash != $rss_hash && count($rss->get_items()) > 0) {
                _debug("saving {$cache_filename}", $debug_enabled);
                @file_put_contents($cache_filename, $feed_data);
            }
        }
        // We use local pluginhost here because we need to load different per-user feed plugins
        $pluginhost->run_hooks(PluginHost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
        _debug("processing feed data...", $debug_enabled);
        //			db_query("BEGIN");
        if (DB_TYPE == "pgsql") {
            $favicon_interval_qpart = "favicon_last_checked < NOW() - INTERVAL '12 hour'";
        } else {
            $favicon_interval_qpart = "favicon_last_checked < DATE_SUB(NOW(), INTERVAL 12 HOUR)";
        }
        $result = db_query("SELECT title,site_url,owner_uid,favicon_avg_color,\n\t\t\t\t(favicon_last_checked IS NULL OR {$favicon_interval_qpart}) AS\n\t\t\t\t\t\tfavicon_needs_check\n\t\t\t\tFROM ttrss_feeds WHERE id = '{$feed}'");
        $registered_title = db_fetch_result($result, 0, "title");
        $orig_site_url = db_fetch_result($result, 0, "site_url");
        $favicon_needs_check = sql_bool_to_bool(db_fetch_result($result, 0, "favicon_needs_check"));
        $favicon_avg_color = db_fetch_result($result, 0, "favicon_avg_color");
        $owner_uid = db_fetch_result($result, 0, "owner_uid");
        $site_url = db_escape_string(mb_substr(rewrite_relative_url($fetch_url, $rss->get_link()), 0, 245));
        _debug("site_url: {$site_url}", $debug_enabled);
        _debug("feed_title: " . $rss->get_title(), $debug_enabled);
        if ($favicon_needs_check || $force_refetch) {
            /* terrible hack: if we crash on floicon shit here, we won't check
             * the icon avgcolor again (unless the icon got updated) */
            $favicon_file = ICONS_DIR . "/{$feed}.ico";
            $favicon_modified = @filemtime($favicon_file);
            _debug("checking favicon...", $debug_enabled);
            check_feed_favicon($site_url, $feed);
            $favicon_modified_new = @filemtime($favicon_file);
            if ($favicon_modified_new > $favicon_modified) {
                $favicon_avg_color = '';
            }
            if (file_exists($favicon_file) && function_exists("imagecreatefromstring") && $favicon_avg_color == '') {
                require_once "colors.php";
                db_query("UPDATE ttrss_feeds SET favicon_avg_color = 'fail' WHERE\n\t\t\t\t\t\t\tid = '{$feed}'");
                $favicon_color = db_escape_string(calculate_avg_color($favicon_file));
                $favicon_colorstring = ",favicon_avg_color = '" . $favicon_color . "'";
            } else {
                if ($favicon_avg_color == 'fail') {
                    _debug("floicon failed on this file, not trying to recalculate avg color", $debug_enabled);
                }
            }
            db_query("UPDATE ttrss_feeds SET favicon_last_checked = NOW()\n\t\t\t\t\t{$favicon_colorstring}\n\t\t\t\t\tWHERE id = '{$feed}'");
        }
        if (!$registered_title || $registered_title == "[Unknown]") {
            $feed_title = db_escape_string($rss->get_title());
            if ($feed_title) {
                _debug("registering title: {$feed_title}", $debug_enabled);
                db_query("UPDATE ttrss_feeds SET\n\t\t\t\t\t\ttitle = '{$feed_title}' WHERE id = '{$feed}'");
            }
        }
        if ($site_url && $orig_site_url != $site_url) {
            db_query("UPDATE ttrss_feeds SET\n\t\t\t\t\tsite_url = '{$site_url}' WHERE id = '{$feed}'");
        }
        _debug("loading filters & labels...", $debug_enabled);
        $filters = load_filters($feed, $owner_uid);
        $labels = get_all_labels($owner_uid);
        _debug("" . count($filters) . " filters loaded.", $debug_enabled);
        $items = $rss->get_items();
        if (!is_array($items)) {
            _debug("no articles found.", $debug_enabled);
            db_query("UPDATE ttrss_feeds\n\t\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
            return;
            // no articles
        }
        if ($pubsub_state != 2 && PUBSUBHUBBUB_ENABLED) {
            _debug("checking for PUSH hub...", $debug_enabled);
            $feed_hub_url = false;
            $links = $rss->get_links('hub');
            if ($links && is_array($links)) {
                foreach ($links as $l) {
                    $feed_hub_url = $l;
                    break;
                }
            }
            _debug("feed hub url: {$feed_hub_url}", $debug_enabled);
            if ($feed_hub_url && function_exists('curl_init') && !ini_get("open_basedir")) {
                require_once 'lib/pubsubhubbub/subscriber.php';
                $callback_url = get_self_url_prefix() . "/public.php?op=pubsub&id={$feed}";
                $s = new Subscriber($feed_hub_url, $callback_url);
                $rc = $s->subscribe($fetch_url);
                _debug("feed hub url found, subscribe request sent.", $debug_enabled);
                db_query("UPDATE ttrss_feeds SET pubsub_state = 1\n\t\t\t\t\t\tWHERE id = '{$feed}'");
            }
        }
        _debug("processing articles...", $debug_enabled);
        foreach ($items as $item) {
            if ($_REQUEST['xdebug'] == 3) {
                print_r($item);
            }
            $entry_guid = $item->get_id();
            if (!$entry_guid) {
                $entry_guid = $item->get_link();
            }
            if (!$entry_guid) {
                $entry_guid = make_guid_from_title($item->get_title());
            }
            _debug("f_guid {$entry_guid}", $debug_enabled);
            if (!$entry_guid) {
                continue;
            }
            $entry_guid = "{$owner_uid},{$entry_guid}";
            $entry_guid_hashed = db_escape_string('SHA1:' . sha1($entry_guid));
            _debug("guid {$entry_guid} / {$entry_guid_hashed}", $debug_enabled);
            $entry_timestamp = "";
            $entry_timestamp = $item->get_date();
            _debug("orig date: " . $item->get_date(), $debug_enabled);
            if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
                $entry_timestamp = time();
                $no_orig_date = 'true';
            } else {
                $no_orig_date = 'false';
            }
            $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
            _debug("date {$entry_timestamp} [{$entry_timestamp_fmt}]", $debug_enabled);
            //				$entry_title = html_entity_decode($item->get_title(), ENT_COMPAT, 'UTF-8');
            //				$entry_title = decode_numeric_entities($entry_title);
            $entry_title = $item->get_title();
            $entry_link = rewrite_relative_url($site_url, $item->get_link());
            _debug("title {$entry_title}", $debug_enabled);
            _debug("link {$entry_link}", $debug_enabled);
            if (!$entry_title) {
                $entry_title = date("Y-m-d H:i:s", $entry_timestamp);
            }
            $entry_content = $item->get_content();
            if (!$entry_content) {
                $entry_content = $item->get_description();
            }
            if ($_REQUEST["xdebug"] == 2) {
                print "content: ";
                print $entry_content;
                print "\n";
            }
            $entry_comments = $item->get_comments_url();
            $entry_author = $item->get_author();
            $entry_guid = db_escape_string(mb_substr($entry_guid, 0, 245));
            $entry_comments = db_escape_string(mb_substr(trim($entry_comments), 0, 245));
            $entry_author = db_escape_string(mb_substr(trim($entry_author), 0, 245));
            $num_comments = (int) $item->get_comments_count();
            _debug("author {$entry_author}", $debug_enabled);
            _debug("num_comments: {$num_comments}", $debug_enabled);
            _debug("looking for tags...", $debug_enabled);
            // parse <category> entries into tags
            $additional_tags = array();
            $additional_tags_src = $item->get_categories();
            if (is_array($additional_tags_src)) {
                foreach ($additional_tags_src as $tobj) {
                    array_push($additional_tags, $tobj);
                }
            }
            $entry_tags = array_unique($additional_tags);
            for ($i = 0; $i < count($entry_tags); $i++) {
                $entry_tags[$i] = mb_strtolower($entry_tags[$i], 'utf-8');
            }
            _debug("tags found: " . join(",", $entry_tags), $debug_enabled);
            _debug("done collecting data.", $debug_enabled);
            // TODO: less memory-hungry implementation
            _debug("applying plugin filters..", $debug_enabled);
            // FIXME not sure if owner_uid is a good idea here, we may have a base entry without user entry (?)
            $result = db_query("SELECT plugin_data,title,content,link,tag_cache,author FROM ttrss_entries, ttrss_user_entries\n\t\t\t\t\tWHERE ref_id = id AND (guid = '" . db_escape_string($entry_guid) . "' OR guid = '{$entry_guid_hashed}') AND owner_uid = {$owner_uid}");
            if (db_num_rows($result) != 0) {
                $entry_plugin_data = db_fetch_result($result, 0, "plugin_data");
                $stored_article = array("title" => db_fetch_result($result, 0, "title"), "content" => db_fetch_result($result, 0, "content"), "link" => db_fetch_result($result, 0, "link"), "tags" => explode(",", db_fetch_result($result, 0, "tag_cache")), "author" => db_fetch_result($result, 0, "author"));
            } else {
                $entry_plugin_data = "";
                $stored_article = array();
            }
            $article = array("owner_uid" => $owner_uid, "guid" => $entry_guid, "title" => $entry_title, "content" => $entry_content, "link" => $entry_link, "tags" => $entry_tags, "plugin_data" => $entry_plugin_data, "author" => $entry_author, "stored" => $stored_article);
            foreach ($pluginhost->get_hooks(PluginHost::HOOK_ARTICLE_FILTER) as $plugin) {
                $article = $plugin->hook_article_filter($article);
            }
            $entry_tags = $article["tags"];
            $entry_guid = db_escape_string($entry_guid);
            $entry_title = db_escape_string($article["title"]);
            $entry_author = db_escape_string($article["author"]);
            $entry_link = db_escape_string($article["link"]);
            $entry_plugin_data = db_escape_string($article["plugin_data"]);
            $entry_content = $article["content"];
            // escaped below
            _debug("plugin data: {$entry_plugin_data}", $debug_enabled);
            if ($cache_images && is_writable(CACHE_DIR . '/images')) {
                cache_images($entry_content, $site_url, $debug_enabled);
            }
            $entry_content = db_escape_string($entry_content, false);
            $content_hash = "SHA1:" . sha1($entry_content);
            db_query("BEGIN");
            $result = db_query("SELECT id FROM\tttrss_entries\n\t\t\t\t\tWHERE (guid = '{$entry_guid}' OR guid = '{$entry_guid_hashed}')");
            if (db_num_rows($result) == 0) {
                _debug("base guid [{$entry_guid}] not found", $debug_enabled);
                // base post entry does not exist, create it
                $result = db_query("INSERT INTO ttrss_entries\n\t\t\t\t\t\t\t(title,\n\t\t\t\t\t\t\tguid,\n\t\t\t\t\t\t\tlink,\n\t\t\t\t\t\t\tupdated,\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tcontent_hash,\n\t\t\t\t\t\t\tno_orig_date,\n\t\t\t\t\t\t\tdate_updated,\n\t\t\t\t\t\t\tdate_entered,\n\t\t\t\t\t\t\tcomments,\n\t\t\t\t\t\t\tnum_comments,\n\t\t\t\t\t\t\tplugin_data,\n\t\t\t\t\t\t\tauthor)\n\t\t\t\t\t\tVALUES\n\t\t\t\t\t\t\t('{$entry_title}',\n\t\t\t\t\t\t\t'{$entry_guid_hashed}',\n\t\t\t\t\t\t\t'{$entry_link}',\n\t\t\t\t\t\t\t'{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t'{$entry_content}',\n\t\t\t\t\t\t\t'{$content_hash}',\n\t\t\t\t\t\t\t{$no_orig_date},\n\t\t\t\t\t\t\tNOW(),\n\t\t\t\t\t\t\t'{$date_feed_processed}',\n\t\t\t\t\t\t\t'{$entry_comments}',\n\t\t\t\t\t\t\t'{$num_comments}',\n\t\t\t\t\t\t\t'{$entry_plugin_data}',\n\t\t\t\t\t\t\t'{$entry_author}')");
                $article_labels = array();
            } else {
                // we keep encountering the entry in feeds, so we need to
                // update date_updated column so that we don't get horrible
                // dupes when the entry gets purged and reinserted again e.g.
                // in the case of SLOW SLOW OMG SLOW updating feeds
                $base_entry_id = db_fetch_result($result, 0, "id");
                db_query("UPDATE ttrss_entries SET date_updated = NOW()\n\t\t\t\t\t\tWHERE id = '{$base_entry_id}'");
                $article_labels = get_article_labels($base_entry_id, $owner_uid);
            }
            // now it should exist, if not - bad luck then
            $result = db_query("SELECT\n\t\t\t\t\t\tid,content_hash,no_orig_date,title,plugin_data,guid,\n\t\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(date_updated,1,19) as date_updated,\n\t\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(updated,1,19) as updated,\n\t\t\t\t\t\tnum_comments\n\t\t\t\t\tFROM\n\t\t\t\t\t\tttrss_entries\n\t\t\t\t\tWHERE guid = '{$entry_guid}' OR guid = '{$entry_guid_hashed}'");
            $entry_ref_id = 0;
            $entry_int_id = 0;
            if (db_num_rows($result) == 1) {
                _debug("base guid found, checking for user record", $debug_enabled);
                // this will be used below in update handler
                $orig_content_hash = db_fetch_result($result, 0, "content_hash");
                $orig_title = db_fetch_result($result, 0, "title");
                $orig_num_comments = db_fetch_result($result, 0, "num_comments");
                $orig_date_updated = strtotime(db_fetch_result($result, 0, "date_updated"));
                $orig_plugin_data = db_fetch_result($result, 0, "plugin_data");
                $ref_id = db_fetch_result($result, 0, "id");
                $entry_ref_id = $ref_id;
                /* $stored_guid = db_fetch_result($result, 0, "guid");
                					if ($stored_guid != $entry_guid_hashed) {
                						if ($debug_enabled) _debug("upgrading compat guid to hashed one", $debug_enabled);
                
                						db_query("UPDATE ttrss_entries SET guid = '$entry_guid_hashed' WHERE
                							id = '$ref_id'");
                					} */
                // check for user post link to main table
                // do we allow duplicate posts with same GUID in different feeds?
                if (get_pref("ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
                    $dupcheck_qpart = "AND (feed_id = '{$feed}' OR feed_id IS NULL)";
                } else {
                    $dupcheck_qpart = "";
                }
                /* Collect article tags here so we could filter by them: */
                $article_filters = get_article_filters($filters, $entry_title, $entry_content, $entry_link, $entry_timestamp, $entry_author, $entry_tags);
                if ($debug_enabled) {
                    _debug("article filters: ", $debug_enabled);
                    if (count($article_filters) != 0) {
                        print_r($article_filters);
                    }
                }
                if (find_article_filter($article_filters, "filter")) {
                    db_query("COMMIT");
                    // close transaction in progress
                    continue;
                }
                $score = calculate_article_score($article_filters);
                _debug("initial score: {$score}", $debug_enabled);
                $query = "SELECT ref_id, int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}'\n\t\t\t\t\t\t\t{$dupcheck_qpart}";
                //					if ($_REQUEST["xdebug"]) print "$query\n";
                $result = db_query($query);
                // okay it doesn't exist - create user entry
                if (db_num_rows($result) == 0) {
                    _debug("user record not found, creating...", $debug_enabled);
                    if ($score >= -500 && !find_article_filter($article_filters, 'catchup')) {
                        $unread = 'true';
                        $last_read_qpart = 'NULL';
                    } else {
                        $unread = 'false';
                        $last_read_qpart = 'NOW()';
                    }
                    if (find_article_filter($article_filters, 'mark') || $score > 1000) {
                        $marked = 'true';
                    } else {
                        $marked = 'false';
                    }
                    if (find_article_filter($article_filters, 'publish')) {
                        $published = 'true';
                    } else {
                        $published = 'false';
                    }
                    // N-grams
                    if (DB_TYPE == "pgsql" and defined('_NGRAM_TITLE_DUPLICATE_THRESHOLD')) {
                        $result = db_query("SELECT COUNT(*) AS similar FROM\n\t\t\t\t\t\t\t\t\tttrss_entries,ttrss_user_entries\n\t\t\t\t\t\t\t\tWHERE ref_id = id AND updated >= NOW() - INTERVAL '7 day'\n\t\t\t\t\t\t\t\t\tAND similarity(title, '{$entry_title}') >= " . _NGRAM_TITLE_DUPLICATE_THRESHOLD . "\n\t\t\t\t\t\t\t\t\tAND owner_uid = {$owner_uid}");
                        $ngram_similar = db_fetch_result($result, 0, "similar");
                        _debug("N-gram similar results: {$ngram_similar}", $debug_enabled);
                        if ($ngram_similar > 0) {
                            $unread = 'false';
                        }
                    }
                    $last_marked = $marked == 'true' ? 'NOW()' : 'NULL';
                    $last_published = $published == 'true' ? 'NOW()' : 'NULL';
                    $result = db_query("INSERT INTO ttrss_user_entries\n\t\t\t\t\t\t\t\t(ref_id, owner_uid, feed_id, unread, last_read, marked,\n\t\t\t\t\t\t\t\tpublished, score, tag_cache, label_cache, uuid,\n\t\t\t\t\t\t\t\tlast_marked, last_published)\n\t\t\t\t\t\t\tVALUES ('{$ref_id}', '{$owner_uid}', '{$feed}', {$unread},\n\t\t\t\t\t\t\t\t{$last_read_qpart}, {$marked}, {$published}, '{$score}', '', '',\n\t\t\t\t\t\t\t\t'', {$last_marked}, {$last_published})");
                    if (PUBSUBHUBBUB_HUB && $published == 'true') {
                        $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key(-2, false, $owner_uid);
                        $p = new Publisher(PUBSUBHUBBUB_HUB);
                        $pubsub_result = $p->publish_update($rss_link);
                    }
                    $result = db_query("SELECT int_id FROM ttrss_user_entries WHERE\n\t\t\t\t\t\t\t\tref_id = '{$ref_id}' AND owner_uid = '{$owner_uid}' AND\n\t\t\t\t\t\t\t\tfeed_id = '{$feed}' LIMIT 1");
                    if (db_num_rows($result) == 1) {
                        $entry_int_id = db_fetch_result($result, 0, "int_id");
                    }
                } else {
                    _debug("user record FOUND", $debug_enabled);
                    $entry_ref_id = db_fetch_result($result, 0, "ref_id");
                    $entry_int_id = db_fetch_result($result, 0, "int_id");
                }
                _debug("RID: {$entry_ref_id}, IID: {$entry_int_id}", $debug_enabled);
                $post_needs_update = false;
                $update_insignificant = false;
                if ($orig_num_comments != $num_comments) {
                    $post_needs_update = true;
                    $update_insignificant = true;
                }
                if ($entry_plugin_data != $orig_plugin_data) {
                    $post_needs_update = true;
                    $update_insignificant = true;
                }
                if ($content_hash != $orig_content_hash) {
                    $post_needs_update = true;
                    $update_insignificant = false;
                }
                if (db_escape_string($orig_title) != $entry_title) {
                    $post_needs_update = true;
                    $update_insignificant = false;
                }
                // if post needs update, update it and mark all user entries
                // linking to this post as updated
                if ($post_needs_update) {
                    if (defined('DAEMON_EXTENDED_DEBUG')) {
                        _debug("post {$entry_guid_hashed} needs update...", $debug_enabled);
                    }
                    //						print "<!-- post $orig_title needs update : $post_needs_update -->";
                    db_query("UPDATE ttrss_entries\n\t\t\t\t\t\t\tSET title = '{$entry_title}', content = '{$entry_content}',\n\t\t\t\t\t\t\t\tcontent_hash = '{$content_hash}',\n\t\t\t\t\t\t\t\tupdated = '{$entry_timestamp_fmt}',\n\t\t\t\t\t\t\t\tnum_comments = '{$num_comments}',\n\t\t\t\t\t\t\t\tplugin_data = '{$entry_plugin_data}'\n\t\t\t\t\t\t\tWHERE id = '{$ref_id}'");
                    if (!$update_insignificant) {
                        if ($mark_unread_on_update) {
                            db_query("UPDATE ttrss_user_entries\n\t\t\t\t\t\t\t\t\tSET last_read = null, unread = true WHERE ref_id = '{$ref_id}'");
                        }
                    }
                }
            }
            db_query("COMMIT");
            _debug("assigning labels...", $debug_enabled);
            assign_article_to_label_filters($entry_ref_id, $article_filters, $owner_uid, $article_labels);
            _debug("looking for enclosures...", $debug_enabled);
            // enclosures
            $enclosures = array();
            $encs = $item->get_enclosures();
            if (is_array($encs)) {
                foreach ($encs as $e) {
                    $e_item = array($e->link, $e->type, $e->length);
                    array_push($enclosures, $e_item);
                }
            }
            if ($debug_enabled) {
                _debug("article enclosures:", $debug_enabled);
                print_r($enclosures);
            }
            db_query("BEGIN");
            foreach ($enclosures as $enc) {
                $enc_url = db_escape_string($enc[0]);
                $enc_type = db_escape_string($enc[1]);
                $enc_dur = db_escape_string($enc[2]);
                $result = db_query("SELECT id FROM ttrss_enclosures\n\t\t\t\t\t\tWHERE content_url = '{$enc_url}' AND post_id = '{$entry_ref_id}'");
                if (db_num_rows($result) == 0) {
                    db_query("INSERT INTO ttrss_enclosures\n\t\t\t\t\t\t\t(content_url, content_type, title, duration, post_id) VALUES\n\t\t\t\t\t\t\t('{$enc_url}', '{$enc_type}', '', '{$enc_dur}', '{$entry_ref_id}')");
                }
            }
            db_query("COMMIT");
            // check for manual tags (we have to do it here since they're loaded from filters)
            foreach ($article_filters as $f) {
                if ($f["type"] == "tag") {
                    $manual_tags = trim_array(explode(",", $f["param"]));
                    foreach ($manual_tags as $tag) {
                        if (tag_is_valid($tag)) {
                            array_push($entry_tags, $tag);
                        }
                    }
                }
            }
            // Skip boring tags
            $boring_tags = trim_array(explode(",", mb_strtolower(get_pref('BLACKLISTED_TAGS', $owner_uid, ''), 'utf-8')));
            $filtered_tags = array();
            $tags_to_cache = array();
            if ($entry_tags && is_array($entry_tags)) {
                foreach ($entry_tags as $tag) {
                    if (array_search($tag, $boring_tags) === false) {
                        array_push($filtered_tags, $tag);
                    }
                }
            }
            $filtered_tags = array_unique($filtered_tags);
            if ($debug_enabled) {
                _debug("filtered article tags:", $debug_enabled);
                print_r($filtered_tags);
            }
            // Save article tags in the database
            if (count($filtered_tags) > 0) {
                db_query("BEGIN");
                foreach ($filtered_tags as $tag) {
                    $tag = sanitize_tag($tag);
                    $tag = db_escape_string($tag);
                    if (!tag_is_valid($tag)) {
                        continue;
                    }
                    $result = db_query("SELECT id FROM ttrss_tags\n\t\t\t\t\t\t\tWHERE tag_name = '{$tag}' AND post_int_id = '{$entry_int_id}' AND\n\t\t\t\t\t\t\towner_uid = '{$owner_uid}' LIMIT 1");
                    if ($result && db_num_rows($result) == 0) {
                        db_query("INSERT INTO ttrss_tags\n\t\t\t\t\t\t\t\t\t(owner_uid,tag_name,post_int_id)\n\t\t\t\t\t\t\t\t\tVALUES ('{$owner_uid}','{$tag}', '{$entry_int_id}')");
                    }
                    array_push($tags_to_cache, $tag);
                }
                /* update the cache */
                $tags_to_cache = array_unique($tags_to_cache);
                $tags_str = db_escape_string(join(",", $tags_to_cache));
                db_query("UPDATE ttrss_user_entries\n\t\t\t\t\t\tSET tag_cache = '{$tags_str}' WHERE ref_id = '{$entry_ref_id}'\n\t\t\t\t\t\tAND owner_uid = {$owner_uid}");
                db_query("COMMIT");
            }
            if (get_pref("AUTO_ASSIGN_LABELS", $owner_uid, false)) {
                _debug("auto-assigning labels...", $debug_enabled);
                foreach ($labels as $label) {
                    $caption = preg_quote($label["caption"]);
                    if ($caption && preg_match("/\\b{$caption}\\b/i", "{$tags_str} " . strip_tags($entry_content) . " {$entry_title}")) {
                        if (!labels_contains_caption($article_labels, $caption)) {
                            label_add_article($entry_ref_id, $caption, $owner_uid);
                        }
                    }
                }
            }
            _debug("article processed", $debug_enabled);
        }
        _debug("purging feed...", $debug_enabled);
        purge_feed($feed, 0, $debug_enabled);
        db_query("UPDATE ttrss_feeds\n\t\t\t\tSET last_updated = NOW(), last_error = '' WHERE id = '{$feed}'");
        //			db_query("COMMIT");
    } else {
        $error_msg = db_escape_string(mb_substr($rss->error(), 0, 245));
        _debug("error fetching feed: {$error_msg}", $debug_enabled);
        db_query("UPDATE ttrss_feeds SET last_error = '{$error_msg}',\n\t\t\t\t\tlast_updated = NOW() WHERE id = '{$feed}'");
    }
    unset($rss);
    _debug("done", $debug_enabled);
}
Beispiel #23
0
 function publ()
 {
     $pub = $_REQUEST["pub"];
     $id = db_escape_string($_REQUEST["id"]);
     $note = trim(strip_tags(db_escape_string($_REQUEST["note"])));
     if ($pub == "1") {
         $pub = "true";
     } else {
         $pub = "false";
     }
     $result = db_query($this->link, "UPDATE ttrss_user_entries SET\n\t\t\tpublished = {$pub}\n\t\t\tWHERE ref_id = '{$id}' AND owner_uid = " . $_SESSION["uid"]);
     $pubsub_result = false;
     if (PUBSUBHUBBUB_HUB) {
         $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key($this->link, -2, false);
         $p = new Publisher(PUBSUBHUBBUB_HUB);
         $pubsub_result = $p->publish_update($rss_link);
     }
     print json_encode(array("message" => "UPDATE_COUNTERS", "pubsub_result" => $pubsub_result));
 }
Beispiel #24
0
 function index()
 {
     print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
     print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Feeds') . "\">";
     $result = $this->dbh->query("SELECT COUNT(id) AS num_errors\n\t\t\tFROM ttrss_feeds WHERE last_error != '' AND owner_uid = " . $_SESSION["uid"]);
     $num_errors = $this->dbh->fetch_result($result, 0, "num_errors");
     if ($num_errors > 0) {
         $error_button = "<button dojoType=\"dijit.form.Button\"\n\t\t\t  \t\tonclick=\"showFeedsWithErrors()\" id=\"errorButton\">" . __("Feeds with errors") . "</button>";
     }
     $inactive_button = "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tid=\"pref_feeds_inactive_btn\"\n\t\t\t\tstyle=\"display : none\"\n\t\t\t\tonclick=\"showInactiveFeeds()\">" . __("Inactive feeds") . "</button>";
     $feed_search = $this->dbh->escape_string($_REQUEST["search"]);
     if (array_key_exists("search", $_REQUEST)) {
         $_SESSION["prefs_feed_search"] = $feed_search;
     } else {
         $feed_search = $_SESSION["prefs_feed_search"];
     }
     print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
     print "<div region='top' dojoType=\"dijit.Toolbar\">";
     #toolbar
     print "<div style='float : right; padding-right : 4px;'>\n\t\t\t<input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"\n\t\t\t\tvalue=\"{$feed_search}\">\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">" . __('Search') . "</button>\n\t\t\t</div>";
     print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Select') . "</span>";
     print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
     print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('All') . "</div>";
     print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('None') . "</div>";
     print "</div></div>";
     print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Feeds') . "</span>";
     print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
     print "<div onclick=\"quickAddFeed()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Subscribe to feed') . "</div>";
     print "<div onclick=\"editSelectedFeed()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Edit selected feeds') . "</div>";
     print "<div onclick=\"resetFeedOrder()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Reset sort order') . "</div>";
     print "<div onclick=\"batchSubscribe()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Batch subscribe') . "</div>";
     print "<div dojoType=\"dijit.MenuItem\" onclick=\"removeSelectedFeeds()\">" . __('Unsubscribe') . "</div> ";
     print "</div></div>";
     if (get_pref('ENABLE_FEED_CATS')) {
         print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Categories') . "</span>";
         print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
         print "<div onclick=\"createCategory()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('Add category') . "</div>";
         print "<div onclick=\"resetCatOrder()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('Reset sort order') . "</div>";
         print "<div onclick=\"removeSelectedCategories()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('Remove selected') . "</div>";
         print "</div></div>";
     }
     print $error_button;
     print $inactive_button;
     if (defined('_ENABLE_FEED_DEBUGGING')) {
         print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">\n\t\t\t\t<option value=\"facDefault\" selected>" . __('More actions...') . "</option>";
         if (FORCE_ARTICLE_PURGE == 0) {
             print "<option value=\"facPurge\">" . __('Manual purge') . "</option>";
         }
         print "\n\t\t\t\t<option value=\"facClear\">" . __('Clear feed data') . "</option>\n\t\t\t\t<option value=\"facRescore\">" . __('Rescore articles') . "</option>";
         print "</select>";
     }
     print "</div>";
     # toolbar
     //print '</div>';
     print '<div dojoType="dijit.layout.ContentPane" region="center">';
     print "<div id=\"feedlistLoading\">\n\t\t<img src='images/indicator_tiny.gif'>" . __("Loading, please wait...") . "</div>";
     print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"\n\t\t\turl=\"backend.php?op=pref-feeds&method=getfeedtree\">\n\t\t</div>\n\t\t<div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"\n\t\tquery=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"\n\t\t\tchildrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">\n\t\t</div>\n\t\t<div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"\n\t\t\tdndController=\"dijit.tree.dndSource\"\n\t\t\tbetweenThreshold=\"5\"\n\t\t\tmodel=\"feedModel\" openOnClick=\"false\">\n\t\t<script type=\"dojo/method\" event=\"onClick\" args=\"item\">\n\t\t\tvar id = String(item.id);\n\t\t\tvar bare_id = id.substr(id.indexOf(':')+1);\n\n\t\t\tif (id.match('FEED:')) {\n\t\t\t\teditFeed(bare_id);\n\t\t\t} else if (id.match('CAT:')) {\n\t\t\t\teditCat(bare_id, item);\n\t\t\t}\n\t\t</script>\n\t\t<script type=\"dojo/method\" event=\"onLoad\" args=\"item\">\n\t\t\tElement.hide(\"feedlistLoading\");\n\n\t\t\tcheckInactiveFeeds();\n\t\t</script>\n\t\t</div>";
     #		print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">
     #			".__('<b>Hint:</b> you can drag feeds and categories around.')."
     #			</div>";
     print '</div>';
     print '</div>';
     print "</div>";
     # feeds pane
     print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('OPML') . "\">";
     print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . __("Only main settings profile can be migrated using OPML.") . "</p>";
     print "<iframe id=\"upload_iframe\"\n\t\t\tname=\"upload_iframe\" onload=\"opmlImportComplete(this)\"\n\t\t\tstyle=\"width: 400px; height: 100px; display: none;\"></iframe>";
     print "<form  name=\"opml_form\" style='display : block' target=\"upload_iframe\"\n\t\t\tenctype=\"multipart/form-data\" method=\"POST\"\n\t\t\taction=\"backend.php\">\n\t\t\t<input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;\n\t\t\t<input type=\"hidden\" name=\"op\" value=\"dlg\">\n\t\t\t<input type=\"hidden\" name=\"method\" value=\"importOpml\">\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" . __('Import my OPML') . "</button>";
     print "<hr>";
     $opml_export_filename = "TinyTinyRSS_" . date("Y-m-d") . ".opml";
     print "<p>" . __('Filename:') . " <input type=\"text\" id=\"filename\" value=\"{$opml_export_filename}\" />&nbsp;" . __('Include settings') . "<input type=\"checkbox\" id=\"settings\" checked=\"1\"/>";
     print "</p><button dojoType=\"dijit.form.Button\"\n\t\t\tonclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" . __('Export OPML') . "</button></p></form>";
     print "<hr>";
     print "<p>" . __('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . "</p>";
     print_warning("Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.");
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('" . __("Public OPML URL") . "','pubOPMLUrl')\">" . __('Display published OPML URL') . "</button> ";
     PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "hook_prefs_tab_section", "prefFeedsOPML");
     print "</div>";
     # pane
     if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
         print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Firefox integration') . "\">";
         print_notice(__('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.'));
         print "<p>";
         print "<button onclick='window.navigator.registerContentHandler(" . "\"application/vnd.mozilla.maybe.feed\", " . "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" . __('Click here to register this site as a feed reader.') . "</button>";
         print "</p>";
         print "</div>";
         # pane
     }
     print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Published & shared articles / Generated feeds') . "\">";
     print "<p>" . __('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.') . "</p>";
     $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() . "/public.php?op=rss&id=-2&view-mode=all_articles");
     print "<p>";
     print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('" . __("View as RSS") . "','generatedFeed', '{$rss_url}')\">" . __('Display URL') . "</button> ";
     print "<button class=\"warning\" dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">" . __('Clear all generated URLs') . "</button> ";
     print "</p>";
     PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "hook_prefs_tab_section", "prefFeedsPublishedGenerated");
     print "</div>";
     #pane
     PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB, "hook_prefs_tab", "prefFeeds");
     print "</div>";
     #container
 }
Beispiel #25
0
 function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes, $article_id)
 {
     $xpath = new DOMXpath($doc);
     if ($article_id) {
         $entries = $xpath->query('(//img[@src])');
         foreach ($entries as $entry) {
             if ($entry->hasAttribute('src')) {
                 $src = rewrite_relative_url($site_url, $entry->getAttribute('src'));
                 $local_filename = $this->cache_dir . $article_id . "-" . sha1($src) . ".png";
                 if (file_exists($local_filename)) {
                     $entry->setAttribute("src", get_self_url_prefix() . "/backend.php?op=pluginhandler&plugin=cache_starred_images&method=image&hash=" . $article_id . "-" . sha1($src));
                 }
             }
         }
     }
     return $doc;
 }
Beispiel #26
0
 private function generate_syndicated_feed($owner_uid, $feed, $is_cat, $limit, $search, $search_mode, $match_on, $view_mode = false)
 {
     require_once "lib/MiniTemplator.class.php";
     $note_style = "background-color : #fff7d5;\n\t\t\tborder-width : 1px; " . "padding : 5px; border-style : dashed; border-color : #e7d796;" . "margin-bottom : 1em; color : #9a8c59;";
     if (!$limit) {
         $limit = 30;
     }
     if (get_pref($this->link, "SORT_HEADLINES_BY_FEED_DATE", $owner_uid)) {
         $date_sort_field = "updated";
     } else {
         $date_sort_field = "date_entered";
     }
     $qfh_ret = queryFeedHeadlines($this->link, $feed, $limit, $view_mode, $is_cat, $search, $search_mode, $match_on, "{$date_sort_field} DESC", 0, $owner_uid);
     $result = $qfh_ret[0];
     $feed_title = htmlspecialchars($qfh_ret[1]);
     $feed_site_url = $qfh_ret[2];
     $last_error = $qfh_ret[3];
     $feed_self_url = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key($this->link, -2, false, $owner_uid);
     if (!$feed_site_url) {
         $feed_site_url = get_self_url_prefix();
     }
     $tpl = new MiniTemplator();
     $tpl->readTemplateFromFile("templates/generated_feed.txt");
     $tpl->setVariable('FEED_TITLE', $feed_title, true);
     $tpl->setVariable('VERSION', VERSION, true);
     $tpl->setVariable('FEED_URL', htmlspecialchars($feed_self_url), true);
     if (PUBSUBHUBBUB_HUB && $feed == -2) {
         $tpl->setVariable('HUB_URL', htmlspecialchars(PUBSUBHUBBUB_HUB), true);
         $tpl->addBlock('feed_hub');
     }
     $tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
     while ($line = db_fetch_assoc($result)) {
         $tpl->setVariable('ARTICLE_ID', htmlspecialchars($line['link']), true);
         $tpl->setVariable('ARTICLE_LINK', htmlspecialchars($line['link']), true);
         $tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
         $tpl->setVariable('ARTICLE_EXCERPT', truncate_string(strip_tags($line["content_preview"]), 100, '...'), true);
         $content = sanitize($this->link, $line["content_preview"], false, $owner_uid);
         if ($line['note']) {
             $content = "<div style=\"{$note_style}\">Article note: " . $line['note'] . "</div>" . $content;
         }
         $tpl->setVariable('ARTICLE_CONTENT', $content, true);
         $tpl->setVariable('ARTICLE_UPDATED_ATOM', date('c', strtotime($line["updated"])), true);
         $tpl->setVariable('ARTICLE_UPDATED_RFC822', date(DATE_RFC822, strtotime($line["updated"])), true);
         $tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
         $tags = get_article_tags($this->link, $line["id"], $owner_uid);
         foreach ($tags as $tag) {
             $tpl->setVariable('ARTICLE_CATEGORY', htmlspecialchars($tag), true);
             $tpl->addBlock('category');
         }
         $enclosures = get_article_enclosures($this->link, $line["id"]);
         foreach ($enclosures as $e) {
             $type = htmlspecialchars($e['content_type']);
             $url = htmlspecialchars($e['content_url']);
             $length = $e['duration'];
             $tpl->setVariable('ARTICLE_ENCLOSURE_URL', $url, true);
             $tpl->setVariable('ARTICLE_ENCLOSURE_TYPE', $type, true);
             $tpl->setVariable('ARTICLE_ENCLOSURE_LENGTH', $length, true);
             $tpl->addBlock('enclosure');
         }
         $tpl->addBlock('entry');
     }
     $tmp = "";
     $tpl->addBlock('feed');
     $tpl->generateOutputToString($tmp);
     print $tmp;
 }
Beispiel #27
0
 function updateArticle()
 {
     $article_ids = array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_ids"])), is_numeric);
     $mode = (int) $this->dbh->escape_string($_REQUEST["mode"]);
     $data = $this->dbh->escape_string($_REQUEST["data"]);
     $field_raw = (int) $this->dbh->escape_string($_REQUEST["field"]);
     $field = "";
     $set_to = "";
     switch ($field_raw) {
         case 0:
             $field = "marked";
             $additional_fields = ",last_marked = NOW()";
             break;
         case 1:
             $field = "published";
             $additional_fields = ",last_published = NOW()";
             break;
         case 2:
             $field = "unread";
             $additional_fields = ",last_read = NOW()";
             break;
         case 3:
             $field = "note";
     }
     switch ($mode) {
         case 1:
             $set_to = "true";
             break;
         case 0:
             $set_to = "false";
             break;
         case 2:
             $set_to = "NOT {$field}";
             break;
     }
     if ($field == "note") {
         $set_to = "'{$data}'";
     }
     if ($field && $set_to && count($article_ids) > 0) {
         $article_ids = join(", ", $article_ids);
         $result = $this->dbh->query("UPDATE ttrss_user_entries SET {$field} = {$set_to} {$additional_fields} WHERE ref_id IN ({$article_ids}) AND owner_uid = " . $_SESSION["uid"]);
         $num_updated = $this->dbh->affected_rows($result);
         if ($num_updated > 0 && $field == "unread") {
             $result = $this->dbh->query("SELECT DISTINCT feed_id FROM ttrss_user_entries\n\t\t\t\t\tWHERE ref_id IN ({$article_ids})");
             while ($line = $this->dbh->fetch_assoc($result)) {
                 ccache_update($line["feed_id"], $_SESSION["uid"]);
             }
         }
         if ($num_updated > 0 && $field == "published") {
             if (PUBSUBHUBBUB_HUB) {
                 $rss_link = get_self_url_prefix() . "/public.php?op=rss&id=-2&key=" . get_feed_access_key(-2, false);
                 $p = new Publisher(PUBSUBHUBBUB_HUB);
                 $pubsub_result = $p->publish_update($rss_link);
             }
         }
         $this->wrap(self::STATUS_OK, array("status" => "OK", "updated" => $num_updated));
     } else {
         $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE'));
     }
 }
Beispiel #28
0
require_once "sessions.php";
require_once "sanity_check.php";
require_once "config.php";
require_once "db.php";
//require_once "lib/twitteroauth/twitteroauth.php";
require_once "lib/tmhoauth/tmhOAuth.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
init_connection($link);
login_sequence($link);
$owner_uid = $_SESSION["uid"];
$op = $_REQUEST['op'];
if (!SINGLE_USER_MODE && !$_SESSION['uid']) {
    render_login_form($link);
    exit;
}
$callback_url = get_self_url_prefix() . "/twitter.php?op=callback";
$tmhOAuth = new tmhOAuth(array('consumer_key' => CONSUMER_KEY, 'consumer_secret' => CONSUMER_SECRET));
if ($op == 'clear') {
    unset($_SESSION['oauth']);
    header("Location: twitter.php");
    return;
}
if (isset($_REQUEST['oauth_verifier'])) {
    $op = 'callback';
    $tmhOAuth->config['user_token'] = $_SESSION['oauth']['oauth_token'];
    $tmhOAuth->config['user_secret'] = $_SESSION['oauth']['oauth_token_secret'];
    $code = $tmhOAuth->request('POST', $tmhOAuth->url('oauth/access_token', ''), array('oauth_verifier' => $_REQUEST['oauth_verifier']));
    if ($code == 200) {
        $access_token = json_encode($tmhOAuth->extract_params($tmhOAuth->response['response']));
        unset($_SESSION['oauth']);
        db_query($link, "UPDATE ttrss_users SET twitter_oauth = '{$access_token}'\n\t\t\t\tWHERE id = " . $_SESSION['uid']);
echo __("Login:"******"text" autocapitalize="off" name="login">
		</div>

		<div class="row">
		<label><?php 
echo __("Password:"******"password" name="password">
		</div>

		</fieldset>

		<div align='center'><a target='_self' href='<?php 
echo get_self_url_prefix();
?>
/index.php?mobile=false'>
			<?php 
echo __("Open regular version");
?>
</a>

	</form>

</body>
</html>

Beispiel #30
0
function module_pref_feeds($link)
{
    global $update_intervals;
    global $purge_intervals;
    global $update_methods;
    $subop = $_REQUEST["subop"];
    $quiet = $_REQUEST["quiet"];
    $mode = $_REQUEST["mode"];
    if ($subop == "renamecat") {
        $title = db_escape_string($_REQUEST['title']);
        $id = db_escape_string($_REQUEST['id']);
        if ($title) {
            db_query($link, "UPDATE ttrss_feed_categories SET\n\t\t\t\t\ttitle = '{$title}' WHERE id = '{$id}' AND owner_uid = " . $_SESSION["uid"]);
        }
        return;
    }
    if ($subop == "remtwitterinfo") {
        db_query($link, "UPDATE ttrss_users SET twitter_oauth = NULL\n\t\t\t\tWHERE id = " . $_SESSION['uid']);
        return;
    }
    if ($subop == "getfeedtree") {
        $search = $_SESSION["prefs_feed_search"];
        if ($search) {
            $search_qpart = " AND LOWER(title) LIKE LOWER('%{$search}%')";
        }
        $root = array();
        $root['id'] = 'root';
        $root['name'] = __('Feeds');
        $root['items'] = array();
        $root['type'] = 'category';
        if (get_pref($link, 'ENABLE_FEED_CATS')) {
            $result = db_query($link, "SELECT id, title FROM ttrss_feed_categories\n\t\t\t\t\tWHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY order_id, title");
            while ($line = db_fetch_assoc($result)) {
                $cat = array();
                $cat['id'] = 'CAT:' . $line['id'];
                $cat['bare_id'] = $feed_id;
                $cat['name'] = $line['title'];
                $cat['items'] = array();
                $cat['checkbox'] = false;
                $cat['type'] = 'category';
                $feed_result = db_query($link, "SELECT id, title, last_error,\n\t\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(last_updated,1,19) AS last_updated\n\t\t\t\t\t\tFROM ttrss_feeds\n\t\t\t\t\t\tWHERE cat_id = '" . $line['id'] . "' AND owner_uid = " . $_SESSION["uid"] . "{$search_qpart} ORDER BY order_id, title");
                while ($feed_line = db_fetch_assoc($feed_result)) {
                    $feed = array();
                    $feed['id'] = 'FEED:' . $feed_line['id'];
                    $feed['bare_id'] = $feed_line['id'];
                    $feed['name'] = $feed_line['title'];
                    $feed['checkbox'] = false;
                    $feed['error'] = $feed_line['last_error'];
                    $feed['icon'] = getFeedIcon($feed_line['id']);
                    $feed['param'] = make_local_datetime($link, $feed_line['last_updated'], true);
                    array_push($cat['items'], $feed);
                }
                $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
                if (count($cat['items']) > 0) {
                    array_push($root['items'], $cat);
                }
                $root['param'] += count($cat['items']);
            }
            /* Uncategorized is a special case */
            $cat = array();
            $cat['id'] = 'CAT:0';
            $cat['bare_id'] = 0;
            $cat['name'] = __("Uncategorized");
            $cat['items'] = array();
            $cat['type'] = 'category';
            $cat['checkbox'] = false;
            $feed_result = db_query($link, "SELECT id, title,last_error,\n\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(last_updated,1,19) AS last_updated\n\t\t\t\t\tFROM ttrss_feeds\n\t\t\t\t\tWHERE cat_id IS NULL AND owner_uid = " . $_SESSION["uid"] . "{$search_qpart} ORDER BY order_id, title");
            while ($feed_line = db_fetch_assoc($feed_result)) {
                $feed = array();
                $feed['id'] = 'FEED:' . $feed_line['id'];
                $feed['bare_id'] = $feed_line['id'];
                $feed['name'] = $feed_line['title'];
                $feed['checkbox'] = false;
                $feed['error'] = $feed_line['last_error'];
                $feed['icon'] = getFeedIcon($feed_line['id']);
                $feed['param'] = make_local_datetime($link, $feed_line['last_updated'], true);
                array_push($cat['items'], $feed);
            }
            $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
            if (count($cat['items']) > 0) {
                array_push($root['items'], $cat);
            }
            $root['param'] += count($cat['items']);
            $root['param'] = T_sprintf('(%d feeds)', $root['param']);
        } else {
            $feed_result = db_query($link, "SELECT id, title, last_error,\n\t\t\t\t\t" . SUBSTRING_FOR_DATE . "(last_updated,1,19) AS last_updated\n\t\t\t\t\tFROM ttrss_feeds\n\t\t\t\t\tWHERE owner_uid = " . $_SESSION["uid"] . "{$search_qpart} ORDER BY order_id, title");
            while ($feed_line = db_fetch_assoc($feed_result)) {
                $feed = array();
                $feed['id'] = 'FEED:' . $feed_line['id'];
                $feed['bare_id'] = $feed_line['id'];
                $feed['name'] = $feed_line['title'];
                $feed['checkbox'] = false;
                $feed['error'] = $feed_line['last_error'];
                $feed['icon'] = getFeedIcon($feed_line['id']);
                $feed['param'] = make_local_datetime($link, $feed_line['last_updated'], true);
                array_push($root['items'], $feed);
            }
            $root['param'] = T_sprintf('(%d feeds)', count($root['items']));
        }
        $fl = array();
        $fl['identifier'] = 'id';
        $fl['label'] = 'name';
        $fl['items'] = array($root);
        print json_encode($fl);
        return;
    }
    if ($subop == "catsortreset") {
        db_query($link, "UPDATE ttrss_feed_categories\n\t\t\t\t\tSET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
        return;
    }
    if ($subop == "feedsortreset") {
        db_query($link, "UPDATE ttrss_feeds\n\t\t\t\t\tSET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
        return;
    }
    if ($subop == "savefeedorder") {
        #			if ($_POST['payload']) {
        #				file_put_contents("/tmp/blahblah.txt", $_POST['payload']);
        #				$data = json_decode($_POST['payload'], true);
        #			} else {
        #				$data = json_decode(file_get_contents("/tmp/blahblah.txt"), true);
        #			}
        $data = json_decode($_POST['payload'], true);
        if (is_array($data) && is_array($data['items'])) {
            $cat_order_id = 0;
            $data_map = array();
            foreach ($data['items'] as $item) {
                if ($item['id'] != 'root') {
                    if (is_array($item['items'])) {
                        if (isset($item['items']['_reference'])) {
                            $data_map[$item['id']] = array($item['items']);
                        } else {
                            $data_map[$item['id']] =& $item['items'];
                        }
                    }
                }
            }
            foreach ($data['items'][0]['items'] as $item) {
                $id = $item['_reference'];
                $bare_id = substr($id, strpos($id, ':') + 1);
                ++$cat_order_id;
                if ($bare_id > 0) {
                    db_query($link, "UPDATE ttrss_feed_categories\n\t\t\t\t\t\t\tSET order_id = '{$cat_order_id}' WHERE id = '{$bare_id}' AND\n\t\t\t\t\t\t\towner_uid = " . $_SESSION["uid"]);
                }
                $feed_order_id = 0;
                if (is_array($data_map[$id])) {
                    foreach ($data_map[$id] as $feed) {
                        $id = $feed['_reference'];
                        $feed_id = substr($id, strpos($id, ':') + 1);
                        if ($bare_id != 0) {
                            $cat_query = "cat_id = '{$bare_id}'";
                        } else {
                            $cat_query = "cat_id = NULL";
                        }
                        db_query($link, "UPDATE ttrss_feeds\n\t\t\t\t\t\t\t\tSET order_id = '{$feed_order_id}',\n\t\t\t\t\t\t\t\t{$cat_query}\n\t\t\t\t\t\t\t\tWHERE id = '{$feed_id}' AND\n\t\t\t\t\t\t\t\t\towner_uid = " . $_SESSION["uid"]);
                        ++$feed_order_id;
                    }
                }
            }
        }
        return;
    }
    if ($subop == "removeicon") {
        $feed_id = db_escape_string($_REQUEST["feed_id"]);
        $result = db_query($link, "SELECT id FROM ttrss_feeds\n\t\t\t\tWHERE id = '{$feed_id}' AND owner_uid = " . $_SESSION["uid"]);
        if (db_num_rows($result) != 0) {
            unlink(ICONS_DIR . "/{$feed_id}.ico");
        }
        return;
    }
    if ($subop == "uploadicon") {
        $icon_file = $_FILES['icon_file']['tmp_name'];
        $feed_id = db_escape_string($_REQUEST["feed_id"]);
        if (is_file($icon_file) && $feed_id) {
            if (filesize($icon_file) < 20000) {
                $result = db_query($link, "SELECT id FROM ttrss_feeds\n\t\t\t\t\t\tWHERE id = '{$feed_id}' AND owner_uid = " . $_SESSION["uid"]);
                if (db_num_rows($result) != 0) {
                    unlink(ICONS_DIR . "/{$feed_id}.ico");
                    move_uploaded_file($icon_file, ICONS_DIR . "/{$feed_id}.ico");
                    $rc = 0;
                } else {
                    $rc = 2;
                }
            } else {
                $rc = 1;
            }
        } else {
            $rc = 2;
        }
        print "<script type=\"text/javascript\">";
        print "parent.uploadIconHandler({$rc});";
        print "</script>";
        return;
    }
    if ($subop == "editfeed") {
        $feed_id = db_escape_string($_REQUEST["id"]);
        $result = db_query($link, "SELECT * FROM ttrss_feeds WHERE id = '{$feed_id}' AND\n\t\t\t\t\towner_uid = " . $_SESSION["uid"]);
        $title = htmlspecialchars(db_fetch_result($result, 0, "title"));
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"{$feed_id}\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"editSave\">";
        print "<div class=\"dlgSec\">" . __("Feed") . "</div>";
        print "<div class=\"dlgSecCont\">";
        /* Title */
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"\n\t\t\t\tplaceHolder=\"" . __("Feed Title") . "\"\n\t\t\t\tstyle=\"font-size : 16px; width: 20em\" name=\"title\" value=\"{$title}\">";
        /* Feed URL */
        $feed_url = db_fetch_result($result, 0, "feed_url");
        $feed_url = htmlspecialchars(db_fetch_result($result, 0, "feed_url"));
        print "<hr/>";
        print __('URL:') . " ";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"\n\t\t\t\tplaceHolder=\"" . __("Feed URL") . "\"\n\t\t\t\tregExp='^(http|https)://.*' style=\"width : 20em\"\n\t\t\t\tname=\"feed_url\" value=\"{$feed_url}\">";
        $last_error = db_fetch_result($result, 0, "last_error");
        if ($last_error) {
            print "&nbsp;<span title=\"" . htmlspecialchars($last_error) . "\"\n\t\t\t\t\tclass=\"feed_error\">(error)</span>";
        }
        /* Category */
        if (get_pref($link, 'ENABLE_FEED_CATS')) {
            $cat_id = db_fetch_result($result, 0, "cat_id");
            print "<hr/>";
            print __('Place in category:') . " ";
            print_feed_cat_select($link, "cat_id", $cat_id, 'dojoType="dijit.form.Select"');
        }
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Update") . "</div>";
        print "<div class=\"dlgSecCont\">";
        /* Update Interval */
        $update_interval = db_fetch_result($result, 0, "update_interval");
        print_select_hash("update_interval", $update_interval, $update_intervals, 'dojoType="dijit.form.Select"');
        /* Update method */
        $update_method = db_fetch_result($result, 0, "update_method", 'dojoType="dijit.form.Select"');
        print " " . __('using') . " ";
        print_select_hash("update_method", $update_method, $update_methods, 'dojoType="dijit.form.Select"');
        $purge_interval = db_fetch_result($result, 0, "purge_interval");
        /* Purge intl */
        print "<hr/>";
        print __('Article purging:') . " ";
        print_select_hash("purge_interval", $purge_interval, $purge_intervals, 'dojoType="dijit.form.Select" ' . (FORCE_ARTICLE_PURGE == 0 ? "" : 'disabled="1"'));
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Authentication") . "</div>";
        print "<div class=\"dlgSecCont\">";
        $auth_login = htmlspecialchars(db_fetch_result($result, 0, "auth_login"));
        #			print "<table>";
        #			print "<tr><td>" . __('Login:'******'<b>Hint:</b> you need to fill in your login information if your feed requires authentication, except for Twitter feeds.') . "\n\t\t\t\t</div>";
        #			print "</td></tr></table>";
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Options") . "</div>";
        print "<div class=\"dlgSecCont\">";
        #			print "<div style=\"line-height : 100%\">";
        $private = sql_bool_to_bool(db_fetch_result($result, 0, "private"));
        if ($private) {
            $checked = "checked=\"1\"";
        } else {
            $checked = "";
        }
        print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"private\" id=\"private\"\n\t\t\t\t{$checked}>&nbsp;<label for=\"private\">" . __('Hide from Popular feeds') . "</label>";
        $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
        if ($rtl_content) {
            $checked = "checked=\"1\"";
        } else {
            $checked = "";
        }
        print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"\n\t\t\t\t{$checked}>&nbsp;<label for=\"rtl_content\">" . __('Right-to-left content') . "</label>";
        $include_in_digest = sql_bool_to_bool(db_fetch_result($result, 0, "include_in_digest"));
        if ($include_in_digest) {
            $checked = "checked=\"1\"";
        } else {
            $checked = "";
        }
        print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"include_in_digest\"\n\t\t\t\tname=\"include_in_digest\"\n\t\t\t\t{$checked}>&nbsp;<label for=\"include_in_digest\">" . __('Include in e-mail digest') . "</label>";
        $always_display_enclosures = sql_bool_to_bool(db_fetch_result($result, 0, "always_display_enclosures"));
        if ($always_display_enclosures) {
            $checked = "checked";
        } else {
            $checked = "";
        }
        print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"always_display_enclosures\"\n\t\t\t\tname=\"always_display_enclosures\"\n\t\t\t\t{$checked}>&nbsp;<label for=\"always_display_enclosures\">" . __('Always display image attachments') . "</label>";
        $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
        if ($cache_images) {
            $checked = "checked=\"1\"";
        } else {
            $checked = "";
        }
        if (SIMPLEPIE_CACHE_IMAGES) {
            print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"cache_images\"\n\t\t\t\tname=\"cache_images\"\n\t\t\t\t{$checked}>&nbsp;<label for=\"cache_images\">" . __('Cache images locally (SimplePie only)') . "</label>";
        }
        $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
        if ($mark_unread_on_update) {
            $checked = "checked";
        } else {
            $checked = "";
        }
        print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"mark_unread_on_update\"\n\t\t\t\tname=\"mark_unread_on_update\"\n\t\t\t\t{$checked}>&nbsp;<label for=\"mark_unread_on_update\">" . __('Mark updated articles as unread') . "</label>";
        $update_on_checksum_change = sql_bool_to_bool(db_fetch_result($result, 0, "update_on_checksum_change"));
        if ($update_on_checksum_change) {
            $checked = "checked";
        } else {
            $checked = "";
        }
        print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"update_on_checksum_change\"\n\t\t\t\tname=\"update_on_checksum_change\"\n\t\t\t\t{$checked}>&nbsp;<label for=\"update_on_checksum_change\">" . __('Mark posts as updated on content change') . "</label>";
        #			print "</div>";
        print "</div>";
        /* Icon */
        print "<div class=\"dlgSec\">" . __("Icon") . "</div>";
        print "<div class=\"dlgSecCont\">";
        print "<iframe name=\"icon_upload_iframe\"\n\t\t\t\tstyle=\"width: 400px; height: 100px; display: none;\"></iframe>";
        print "<form style='display : block' target=\"icon_upload_iframe\"\n\t\t\t\tenctype=\"multipart/form-data\" method=\"POST\"\n\t\t\t\taction=\"backend.php\">\n\t\t\t\t<input id=\"icon_file\" size=\"10\" name=\"icon_file\" type=\"file\">\n\t\t\t\t<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">\n\t\t\t\t<input type=\"hidden\" name=\"feed_id\" value=\"{$feed_id}\">\n\t\t\t\t<input type=\"hidden\" name=\"subop\" value=\"uploadicon\">\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"\n\t\t\t\t\ttype=\"submit\">" . __('Replace') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon({$feed_id});\"\n\t\t\t\t\ttype=\"submit\">" . __('Remove') . "</button>\n\t\t\t\t</form>";
        print "</div>";
        $title = htmlspecialchars($title, ENT_QUOTES);
        print "<div class='dlgButtons'>\n\t\t\t\t<div style=\"float : left\">\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick='return unsubscribeFeed({$feed_id}, \"{$title}\")'>" . __('Unsubscribe') . "</button>";
        if (PUBSUBHUBBUB_ENABLED) {
            $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
            $pubsub_btn_disabled = $pubsub_state == 2 ? "" : "disabled=\"1\"";
            print "<button dojoType=\"dijit.form.Button\" id=\"pubsubReset_Btn\" {$pubsub_btn_disabled}\n\t\t\t\t\t\tonclick='return resetPubSub({$feed_id}, \"{$title}\")'>" . __('Resubscribe to push updates') . "</button>";
        }
        print "</div>";
        print "<div dojoType=\"dijit.Tooltip\" connectId=\"pubsubReset_Btn\" position=\"below\">" . __('Resets PubSubHubbub subscription status for push-enabled feeds.') . "</div>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').execute()\">" . __('Save') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').hide()\">" . __('Cancel') . "</button>\n\t\t\t</div>";
        return;
    }
    if ($subop == "editfeeds") {
        $feed_ids = db_escape_string($_REQUEST["ids"]);
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"ids\" value=\"{$feed_ids}\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
        print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"subop\" value=\"batchEditSave\">";
        print "<div class=\"dlgSec\">" . __("Feed") . "</div>";
        print "<div class=\"dlgSecCont\">";
        /* Title */
        print "<input dojoType=\"dijit.form.ValidationTextBox\"\n\t\t\t\tdisabled=\"1\" style=\"font-size : 16px; width : 20em;\" required=\"1\"\n\t\t\t\tname=\"title\" value=\"{$title}\">";
        batch_edit_cbox("title");
        /* Feed URL */
        print "<br/>";
        print __('URL:') . " ";
        print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\"\n\t\t\t\trequired=\"1\" regExp='^(http|https)://.*' style=\"width : 20em\"\n\t\t\t\tname=\"feed_url\" value=\"{$feed_url}\">";
        batch_edit_cbox("feed_url");
        /* Category */
        if (get_pref($link, 'ENABLE_FEED_CATS')) {
            print "<br/>";
            print __('Place in category:') . " ";
            print_feed_cat_select($link, "cat_id", $cat_id, 'disabled="1" dojoType="dijit.form.Select"');
            batch_edit_cbox("cat_id");
        }
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Update") . "</div>";
        print "<div class=\"dlgSecCont\">";
        /* Update Interval */
        print_select_hash("update_interval", $update_interval, $update_intervals, 'disabled="1" dojoType="dijit.form.Select"');
        batch_edit_cbox("update_interval");
        /* Update method */
        print " " . __('using') . " ";
        print_select_hash("update_method", $update_method, $update_methods, 'disabled="1" dojoType="dijit.form.Select"');
        batch_edit_cbox("update_method");
        /* Purge intl */
        if (FORCE_ARTICLE_PURGE == 0) {
            print "<br/>";
            print __('Article purging:') . " ";
            print_select_hash("purge_interval", $purge_interval, $purge_intervals, 'disabled="1" dojoType="dijit.form.Select"');
            batch_edit_cbox("purge_interval");
        }
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Authentication") . "</div>";
        print "<div class=\"dlgSecCont\">";
        print "<input dojoType=\"dijit.form.TextBox\"\n\t\t\t\tplaceHolder=\"" . __("Login") . "\" disabled=\"1\"\n\t\t\t\tname=\"auth_login\" value=\"{$auth_login}\">";
        batch_edit_cbox("auth_login");
        print "<br/><input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"\n\t\t\t\tplaceHolder=\"" . __("Password") . "\" disabled=\"1\"\n\t\t\t\tvalue=\"{$auth_pass}\">";
        batch_edit_cbox("auth_pass");
        print "</div>";
        print "<div class=\"dlgSec\">" . __("Options") . "</div>";
        print "<div class=\"dlgSecCont\">";
        print "<input disabled=\"1\" type=\"checkbox\" name=\"private\" id=\"private\"\n\t\t\t\tdojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"private_l\" class='insensitive' for=\"private\">" . __('Hide from Popular feeds') . "</label>";
        print "&nbsp;";
        batch_edit_cbox("private", "private_l");
        print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"\n\t\t\t\tdojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"rtl_content_l\" for=\"rtl_content\">" . __('Right-to-left content') . "</label>";
        print "&nbsp;";
        batch_edit_cbox("rtl_content", "rtl_content_l");
        print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"include_in_digest\"\n\t\t\t\tname=\"include_in_digest\"\n\t\t\t\tdojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"include_in_digest_l\" class='insensitive' for=\"include_in_digest\">" . __('Include in e-mail digest') . "</label>";
        print "&nbsp;";
        batch_edit_cbox("include_in_digest", "include_in_digest_l");
        print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"always_display_enclosures\"\n\t\t\t\tname=\"always_display_enclosures\"\n\t\t\t\tdojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"always_display_enclosures_l\" class='insensitive' for=\"always_display_enclosures\">" . __('Always display image attachments') . "</label>";
        print "&nbsp;";
        batch_edit_cbox("always_display_enclosures", "always_display_enclosures_l");
        if (SIMPLEPIE_CACHE_IMAGES) {
            print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"cache_images\"\n\t\t\t\t\tname=\"cache_images\"\n\t\t\t\t\tdojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"cache_images_l\"\n\t\t\t\t\tfor=\"cache_images\">" . __('Cache images locally') . "</label>";
            print "&nbsp;";
            batch_edit_cbox("cache_images", "cache_images_l");
        }
        print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"mark_unread_on_update\"\n\t\t\t\tname=\"mark_unread_on_update\"\n\t\t\t\tdojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"mark_unread_on_update_l\" class='insensitive' for=\"mark_unread_on_update\">" . __('Mark updated articles as unread') . "</label>";
        print "&nbsp;";
        batch_edit_cbox("mark_unread_on_update", "mark_unread_on_update_l");
        print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"update_on_checksum_change\"\n\t\t\t\tname=\"update_on_checksum_change\"\n\t\t\t\tdojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"update_on_checksum_change_l\" class='insensitive' for=\"update_on_checksum_change\">" . __('Mark posts as updated on content change') . "</label>";
        print "&nbsp;";
        batch_edit_cbox("update_on_checksum_change", "update_on_checksum_change_l");
        print "</div>";
        print "<div class='dlgButtons'>\n\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\t\tonclick=\"return dijit.byId('feedEditDlg').execute()\">" . __('Save') . "</button>\n\t\t\t\t<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return dijit.byId('feedEditDlg').hide()\">" . __('Cancel') . "</button>\n\t\t\t\t</div>";
        return;
    }
    if ($subop == "editSave" || $subop == "batchEditSave") {
        $feed_title = db_escape_string(trim($_POST["title"]));
        $feed_link = db_escape_string(trim($_POST["feed_url"]));
        $upd_intl = (int) db_escape_string($_POST["update_interval"]);
        $purge_intl = (int) db_escape_string($_POST["purge_interval"]);
        $feed_id = (int) db_escape_string($_POST["id"]);
        /* editSave */
        $feed_ids = db_escape_string($_POST["ids"]);
        /* batchEditSave */
        $cat_id = (int) db_escape_string($_POST["cat_id"]);
        $auth_login = db_escape_string(trim($_POST["auth_login"]));
        $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
        $private = checkbox_to_sql_bool(db_escape_string($_POST["private"]));
        $rtl_content = checkbox_to_sql_bool(db_escape_string($_POST["rtl_content"]));
        $include_in_digest = checkbox_to_sql_bool(db_escape_string($_POST["include_in_digest"]));
        $cache_images = checkbox_to_sql_bool(db_escape_string($_POST["cache_images"]));
        $update_method = (int) db_escape_string($_POST["update_method"]);
        $always_display_enclosures = checkbox_to_sql_bool(db_escape_string($_POST["always_display_enclosures"]));
        $mark_unread_on_update = checkbox_to_sql_bool(db_escape_string($_POST["mark_unread_on_update"]));
        $update_on_checksum_change = checkbox_to_sql_bool(db_escape_string($_POST["update_on_checksum_change"]));
        if (get_pref($link, 'ENABLE_FEED_CATS')) {
            if ($cat_id && $cat_id != 0) {
                $category_qpart = "cat_id = '{$cat_id}',";
                $category_qpart_nocomma = "cat_id = '{$cat_id}'";
            } else {
                $category_qpart = 'cat_id = NULL,';
                $category_qpart_nocomma = 'cat_id = NULL';
            }
        } else {
            $category_qpart = "";
            $category_qpart_nocomma = "";
        }
        if (SIMPLEPIE_CACHE_IMAGES) {
            $cache_images_qpart = "cache_images = {$cache_images},";
        } else {
            $cache_images_qpart = "";
        }
        if ($subop == "editSave") {
            $result = db_query($link, "UPDATE ttrss_feeds SET\n\t\t\t\t\t{$category_qpart}\n\t\t\t\t\ttitle = '{$feed_title}', feed_url = '{$feed_link}',\n\t\t\t\t\tupdate_interval = '{$upd_intl}',\n\t\t\t\t\tpurge_interval = '{$purge_intl}',\n\t\t\t\t\tauth_login = '******',\n\t\t\t\t\tauth_pass = '******',\n\t\t\t\t\tprivate = {$private},\n\t\t\t\t\trtl_content = {$rtl_content},\n\t\t\t\t\t{$cache_images_qpart}\n\t\t\t\t\tinclude_in_digest = {$include_in_digest},\n\t\t\t\t\talways_display_enclosures = {$always_display_enclosures},\n\t\t\t\t\tmark_unread_on_update = {$mark_unread_on_update},\n\t\t\t\t\tupdate_on_checksum_change = {$update_on_checksum_change},\n\t\t\t\t\tupdate_method = '{$update_method}'\n\t\t\t\t\tWHERE id = '{$feed_id}' AND owner_uid = " . $_SESSION["uid"]);
        } else {
            if ($subop == "batchEditSave") {
                $feed_data = array();
                foreach (array_keys($_POST) as $k) {
                    if ($k != "op" && $k != "subop" && $k != "ids") {
                        $feed_data[$k] = $_POST[$k];
                    }
                }
                db_query($link, "BEGIN");
                foreach (array_keys($feed_data) as $k) {
                    $qpart = "";
                    switch ($k) {
                        case "title":
                            $qpart = "title = '{$feed_title}'";
                            break;
                        case "feed_url":
                            $qpart = "feed_url = '{$feed_link}'";
                            break;
                        case "update_interval":
                            $qpart = "update_interval = '{$upd_intl}'";
                            break;
                        case "purge_interval":
                            $qpart = "purge_interval = '{$purge_intl}'";
                            break;
                        case "auth_login":
                            $qpart = "auth_login = '******'";
                            break;
                        case "auth_pass":
                            $qpart = "auth_pass = '******'";
                            break;
                        case "private":
                            $qpart = "private = '{$private}'";
                            break;
                        case "include_in_digest":
                            $qpart = "include_in_digest = '{$include_in_digest}'";
                            break;
                        case "always_display_enclosures":
                            $qpart = "always_display_enclosures = '{$always_display_enclosures}'";
                            break;
                        case "mark_unread_on_update":
                            $qpart = "mark_unread_on_update = '{$mark_unread_on_update}'";
                            break;
                        case "update_on_checksum_change":
                            $qpart = "update_on_checksum_change = '{$update_on_checksum_change}'";
                            break;
                        case "cache_images":
                            $qpart = "cache_images = '{$cache_images}'";
                            break;
                        case "rtl_content":
                            $qpart = "rtl_content = '{$rtl_content}'";
                            break;
                        case "update_method":
                            $qpart = "update_method = '{$update_method}'";
                            break;
                        case "cat_id":
                            $qpart = $category_qpart_nocomma;
                            break;
                    }
                    if ($qpart) {
                        db_query($link, "UPDATE ttrss_feeds SET {$qpart} WHERE id IN ({$feed_ids})\n\t\t\t\t\t\t\tAND owner_uid = " . $_SESSION["uid"]);
                        print "<br/>";
                    }
                }
                db_query($link, "COMMIT");
            }
        }
        return;
    }
    if ($subop == "resetPubSub") {
        $ids = db_escape_string($_REQUEST["ids"]);
        db_query($link, "UPDATE ttrss_feeds SET pubsub_state = 0 WHERE id IN ({$ids})\n\t\t\t\tAND owner_uid = " . $_SESSION["uid"]);
        return;
    }
    if ($subop == "remove") {
        $ids = split(",", db_escape_string($_REQUEST["ids"]));
        foreach ($ids as $id) {
            remove_feed($link, $id, $_SESSION["uid"]);
        }
        return;
    }
    if ($subop == "clear") {
        $id = db_escape_string($_REQUEST["id"]);
        clear_feed_articles($link, $id);
    }
    if ($subop == "rescore") {
        $ids = split(",", db_escape_string($_REQUEST["ids"]));
        foreach ($ids as $id) {
            $filters = load_filters($link, $id, $_SESSION["uid"], 6);
            $result = db_query($link, "SELECT\n\t\t\t\t\ttitle, content, link, ref_id, author," . SUBSTRING_FOR_DATE . "(updated, 1, 19) AS updated\n\t\t\t\t  \tFROM\n\t\t\t\t\t\tttrss_user_entries, ttrss_entries\n\t\t\t\t\t\tWHERE ref_id = id AND feed_id = '{$id}' AND\n\t\t\t\t\t\t\towner_uid = " . $_SESSION['uid'] . "\n\t\t\t\t\t\t");
            $scores = array();
            while ($line = db_fetch_assoc($result)) {
                $tags = get_article_tags($link, $line["ref_id"]);
                $article_filters = get_article_filters($filters, $line['title'], $line['content'], $line['link'], strtotime($line['updated']), $line['author'], $tags);
                $new_score = calculate_article_score($article_filters);
                if (!$scores[$new_score]) {
                    $scores[$new_score] = array();
                }
                array_push($scores[$new_score], $line['ref_id']);
            }
            foreach (array_keys($scores) as $s) {
                if ($s > 1000) {
                    db_query($link, "UPDATE ttrss_user_entries SET score = '{$s}',\n\t\t\t\t\t\t\tmarked = true WHERE\n\t\t\t\t\t\t\tref_id IN (" . join(',', $scores[$s]) . ")");
                } else {
                    if ($s < -500) {
                        db_query($link, "UPDATE ttrss_user_entries SET score = '{$s}',\n\t\t\t\t\t\t\tunread = false WHERE\n\t\t\t\t\t\t\tref_id IN (" . join(',', $scores[$s]) . ")");
                    } else {
                        db_query($link, "UPDATE ttrss_user_entries SET score = '{$s}' WHERE\n\t\t\t\t\t\t\tref_id IN (" . join(',', $scores[$s]) . ")");
                    }
                }
            }
        }
        print __("All done.");
    }
    if ($subop == "rescoreAll") {
        $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE owner_uid = " . $_SESSION['uid']);
        while ($feed_line = db_fetch_assoc($result)) {
            $id = $feed_line["id"];
            $filters = load_filters($link, $id, $_SESSION["uid"], 6);
            $tmp_result = db_query($link, "SELECT\n\t\t\t\t\ttitle, content, link, ref_id, author," . SUBSTRING_FOR_DATE . "(updated, 1, 19) AS updated\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\tttrss_user_entries, ttrss_entries\n\t\t\t\t\t\tWHERE ref_id = id AND feed_id = '{$id}' AND\n\t\t\t\t\t\t\towner_uid = " . $_SESSION['uid'] . "\n\t\t\t\t\t\t");
            $scores = array();
            while ($line = db_fetch_assoc($tmp_result)) {
                $tags = get_article_tags($link, $line["ref_id"]);
                $article_filters = get_article_filters($filters, $line['title'], $line['content'], $line['link'], strtotime($line['updated']), $line['author'], $tags);
                $new_score = calculate_article_score($article_filters);
                if (!$scores[$new_score]) {
                    $scores[$new_score] = array();
                }
                array_push($scores[$new_score], $line['ref_id']);
            }
            foreach (array_keys($scores) as $s) {
                if ($s > 1000) {
                    db_query($link, "UPDATE ttrss_user_entries SET score = '{$s}',\n\t\t\t\t\t\t\tmarked = true WHERE\n\t\t\t\t\t\t\tref_id IN (" . join(',', $scores[$s]) . ")");
                } else {
                    db_query($link, "UPDATE ttrss_user_entries SET score = '{$s}' WHERE\n\t\t\t\t\t\t\tref_id IN (" . join(',', $scores[$s]) . ")");
                }
            }
        }
        print __("All done.");
    }
    if ($subop == "add") {
        $feed_url = db_escape_string(trim($_REQUEST["feed_url"]));
        $cat_id = db_escape_string($_REQUEST["cat_id"]);
        $p_from = db_escape_string($_REQUEST["from"]);
        /* only read authentication information from POST */
        $auth_login = db_escape_string(trim($_POST["auth_login"]));
        $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
        if ($p_from != 'tt-rss') {
            header("Content-Type: text/html");
            print "<html>\n\t\t\t\t\t<head>\n\t\t\t\t\t\t<title>Tiny Tiny RSS</title>\n\t\t\t\t\t\t<link rel=\"stylesheet\" type=\"text/css\" href=\"utility.css\">\n\t\t\t\t\t</head>\n\t\t\t\t\t<body>\n\t\t\t\t\t<img class=\"floatingLogo\" src=\"images/ttrss_logo.png\"\n\t\t\t\t  \t\talt=\"Tiny Tiny RSS\"/>\n\t\t\t\t\t<h1>Subscribe to feed...</h1>";
        }
        $rc = subscribe_to_feed($link, $feed_url, $cat_id, $auth_login, $auth_pass);
        switch ($rc) {
            case 1:
                print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
                break;
            case 2:
                print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
                break;
            case 3:
                print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
                break;
            case 0:
                print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
                break;
            case 4:
                print_notice("Multiple feed URLs found.");
                $feed_urls = get_feeds_from_html($feed_url);
                break;
            case 5:
                print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
                break;
        }
        if ($p_from != 'tt-rss') {
            if ($feed_urls) {
                print "<form action=\"backend.php\">";
                print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
                print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
                print "<input type=\"hidden\" name=\"subop\" value=\"add\">";
                print "<select name=\"feed_url\">";
                foreach ($feed_urls as $url => $name) {
                    $url = htmlspecialchars($url);
                    $name = htmlspecialchars($name);
                    print "<option value=\"{$url}\">{$name}</option>";
                }
                print "<input type=\"submit\" value=\"" . __("Subscribe to selected feed") . "\">";
                print "</form>";
            }
            $tp_uri = get_self_url_prefix() . "/prefs.php";
            $tt_uri = get_self_url_prefix();
            if ($rc <= 2) {
                $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE\n\t\t\t\t\t\tfeed_url = '{$feed_url}' AND owner_uid = " . $_SESSION["uid"]);
                $feed_id = db_fetch_result($result, 0, "id");
            } else {
                $feed_id = 0;
            }
            print "<p>";
            if ($feed_id) {
                print "<form method=\"GET\" style='display: inline'\n\t\t\t\t\t\taction=\"{$tp_uri}\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"tab\" value=\"feedConfig\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"subop\" value=\"editFeed\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"subopparam\" value=\"{$feed_id}\">\n\t\t\t\t\t\t<input type=\"submit\" value=\"" . __("Edit subscription options") . "\">\n\t\t\t\t\t\t</form>";
            }
            print "<form style='display: inline' method=\"GET\" action=\"{$tt_uri}\">\n\t\t\t\t\t<input type=\"submit\" value=\"" . __("Return to Tiny Tiny RSS") . "\">\n\t\t\t\t\t</form></p>";
            print "</body></html>";
            return;
        }
    }
    if ($subop == "categorize") {
        $ids = split(",", db_escape_string($_REQUEST["ids"]));
        $cat_id = db_escape_string($_REQUEST["cat_id"]);
        if ($cat_id == 0) {
            $cat_id_qpart = 'NULL';
        } else {
            $cat_id_qpart = "'{$cat_id}'";
        }
        db_query($link, "BEGIN");
        foreach ($ids as $id) {
            db_query($link, "UPDATE ttrss_feeds SET cat_id = {$cat_id_qpart}\n\t\t\t\t\tWHERE id = '{$id}'\n\t\t\t\t  \tAND owner_uid = " . $_SESSION["uid"]);
        }
        db_query($link, "COMMIT");
    }
    if ($subop == "editCats") {
        $action = $_REQUEST["action"];
        if ($action == "save") {
            $cat_title = db_escape_string(trim($_REQUEST["value"]));
            $cat_id = db_escape_string($_REQUEST["cid"]);
            db_query($link, "BEGIN");
            $result = db_query($link, "SELECT title FROM ttrss_feed_categories\n\t\t\t\t\tWHERE id = '{$cat_id}' AND owner_uid = " . $_SESSION["uid"]);
            if (db_num_rows($result) == 1) {
                $old_title = db_fetch_result($result, 0, "title");
                if ($cat_title != "") {
                    $result = db_query($link, "UPDATE ttrss_feed_categories SET\n\t\t\t\t\t\t\ttitle = '{$cat_title}' WHERE id = '{$cat_id}' AND\n\t\t\t\t\t\t\towner_uid = " . $_SESSION["uid"]);
                    print $cat_title;
                } else {
                    print $old_title;
                }
            } else {
                print $_REQUEST["value"];
            }
            db_query($link, "COMMIT");
            return;
        }
        if ($action == "add") {
            $feed_cat = db_escape_string(trim($_REQUEST["cat"]));
            if (!add_feed_category($link, $feed_cat)) {
                print_warning(T_sprintf("Category <b>\$%s</b> already exists in the database.", $feed_cat));
            }
        }
        if ($action == "remove") {
            $ids = split(",", db_escape_string($_REQUEST["ids"]));
            foreach ($ids as $id) {
                remove_feed_category($link, $id, $_SESSION["uid"]);
            }
        }
        print "<div dojoType=\"dijit.Toolbar\">\n\t\t\t\t<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"newcat\">\n\t\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').addCategory()\">" . __('Create category') . "</button></div>";
        $result = db_query($link, "SELECT title,id FROM ttrss_feed_categories\n\t\t\t\tWHERE owner_uid = " . $_SESSION["uid"] . "\n\t\t\t\tORDER BY title");
        #			print "<p>";
        if (db_num_rows($result) != 0) {
            print "<div class=\"prefFeedCatHolder\">";
            #				print "<form id=\"feed_cat_edit_form\" onsubmit=\"return false\">";
            print "<table width=\"100%\" class=\"prefFeedCatList\"\n\t\t\t\t\tcellspacing=\"0\" id=\"prefFeedCatList\">";
            $lnum = 0;
            while ($line = db_fetch_assoc($result)) {
                $class = $lnum % 2 ? "even" : "odd";
                $cat_id = $line["id"];
                $this_row_id = "id=\"FCATR-{$cat_id}\"";
                print "<tr class=\"\" {$this_row_id}>";
                $edit_title = htmlspecialchars($line["title"]);
                print "<td width='5%' align='center'><input\n\t\t\t\t\t\tonclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"\n\t\t\t\t\t\ttype=\"checkbox\"></td>";
                print "<td>";
                #					print "<span id=\"FCATT-$cat_id\">" .
                #						$edit_title . "</span>";
                print "<span dojoType=\"dijit.InlineEditBox\"\n\t\t\t\t\t\twidth=\"300px\" autoSave=\"false\"\n\t\t\t\t\t\tcat-id=\"{$cat_id}\">" . $edit_title . "<script type=\"dojo/method\" event=\"onChange\" args=\"item\">\n\t\t\t\t\t\t\tvar elem = this;\n\t\t\t\t\t\t\tdojo.xhrPost({\n\t\t\t\t\t\t\t\turl: 'backend.php',\n\t\t\t\t\t\t\t\tcontent: {op: 'pref-feeds', subop: 'editCats',\n\t\t\t\t\t\t\t\t\taction: 'save',\n\t\t\t\t\t\t\t\t\tvalue: this.value,\n\t\t\t\t\t\t\t\t\tcid: this.srcNodeRef.getAttribute('cat-id')},\n\t\t\t\t\t\t\t\t\tload: function(response) {\n\t\t\t\t\t\t\t\t\t\telem.attr('value', response);\n\t\t\t\t\t\t\t\t\t\tupdateFeedList();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t</script>\n\t\t\t\t\t</span>";
                print "</td></tr>";
                ++$lnum;
            }
            print "</table>";
            #				print "</form>";
            print "</div>";
        } else {
            print "<p>" . __('No feed categories defined.') . "</p>";
        }
        print "<div class='dlgButtons'>\n\t\t\t\t<div style='float : left'>\n\t\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').removeSelected()\">" . __('Remove selected categories') . "</button>\n\t\t\t\t</div>";
        print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').hide()\">" . __('Close this window') . "</button></div>";
        return;
    }
    if ($quiet) {
        return;
    }
    print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
    print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Feeds') . "\">";
    /* print "<div dojoType=\"dijit.layout.BorderContainer\">";
    		print "<
    			print "</div>"; */
    $result = db_query($link, "SELECT COUNT(id) AS num_errors\n\t\t\tFROM ttrss_feeds WHERE last_error != '' AND owner_uid = " . $_SESSION["uid"]);
    $num_errors = db_fetch_result($result, 0, "num_errors");
    if ($num_errors > 0) {
        $error_button = "<button dojoType=\"dijit.form.Button\"\n\t\t\t  \t\tonclick=\"showFeedsWithErrors()\" id=\"errorButton\">" . __("Feeds with errors") . "</button>";
        //			print format_notice("<a href=\"javascript:showFeedsWithErrors()\">".
        //				__('Some feeds have update errors (click for details)')."</a>");
    }
    if (DB_TYPE == "pgsql") {
        $interval_qpart = "NOW() - INTERVAL '3 months'";
    } else {
        $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
    }
    $result = db_query($link, "SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE\n\t\t\t\t\t(SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE\n\t\t\t\t\t\tttrss_entries.id = ref_id AND\n\t\t\t\t\t\t\tttrss_user_entries.feed_id = ttrss_feeds.id) < {$interval_qpart} AND\n\t\t\tttrss_feeds.owner_uid = " . $_SESSION["uid"]);
    $num_inactive = db_fetch_result($result, 0, "num_inactive");
    if ($num_inactive > 0) {
        $inactive_button = "<button dojoType=\"dijit.form.Button\"\n\t\t\t  \t\tonclick=\"showInactiveFeeds()\">" . __("Inactive feeds") . "</button>";
    }
    $feed_search = db_escape_string($_REQUEST["search"]);
    if (array_key_exists("search", $_REQUEST)) {
        $_SESSION["prefs_feed_search"] = $feed_search;
    } else {
        $feed_search = $_SESSION["prefs_feed_search"];
    }
    print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
    print "<div region='top' dojoType=\"dijit.Toolbar\">";
    #toolbar
    print "<div style='float : right; padding-right : 4px;'>\n\t\t\t<input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"\n\t\t\t\tvalue=\"{$feed_search}\">\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">" . __('Search') . "</button>\n\t\t\t</div>";
    print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Select') . "</span>";
    print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
    print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('All') . "</div>";
    print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('None') . "</div>";
    print "</div></div>";
    print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Feeds') . "</span>";
    print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
    print "<div onclick=\"quickAddFeed()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Subscribe to feed') . "</div>";
    print "<div onclick=\"editSelectedFeed()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Edit selected feeds') . "</div>";
    print "<div onclick=\"resetFeedOrder()\"\n\t\t\tdojoType=\"dijit.MenuItem\">" . __('Reset sort order') . "</div>";
    print "</div></div>";
    if (get_pref($link, 'ENABLE_FEED_CATS')) {
        print "<div dojoType=\"dijit.form.DropDownButton\">" . "<span>" . __('Categories') . "</span>";
        print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
        print "<div onclick=\"editFeedCats()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('Edit categories') . "</div>";
        print "<div onclick=\"resetCatOrder()\"\n\t\t\t\tdojoType=\"dijit.MenuItem\">" . __('Reset sort order') . "</div>";
        print "</div></div>";
    }
    print $error_button;
    print $inactive_button;
    print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedFeeds()\">" . __('Unsubscribe') . "</button dojoType=\"dijit.form.Button\"> ";
    if (defined('_ENABLE_FEED_DEBUGGING')) {
        print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">\n\t\t\t\t<option value=\"facDefault\" selected>" . __('More actions...') . "</option>";
        if (FORCE_ARTICLE_PURGE == 0) {
            print "<option value=\"facPurge\">" . __('Manual purge') . "</option>";
        }
        print "\n\t\t\t\t<option value=\"facClear\">" . __('Clear feed data') . "</option>\n\t\t\t\t<option value=\"facRescore\">" . __('Rescore articles') . "</option>";
        print "</select>";
    }
    print "</div>";
    # toolbar
    //print '</div>';
    print '<div dojoType="dijit.layout.ContentPane" region="center">';
    print "<div id=\"feedlistLoading\">\n\t\t<img src='images/indicator_tiny.gif'>" . __("Loading, please wait...") . "</div>";
    print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"\n\t\t\turl=\"backend.php?op=pref-feeds&subop=getfeedtree\">\n\t\t</div>\n\t\t<div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"\n\t\tquery=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"\n\t\t\tchildrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">\n\t\t</div>\n\t\t<div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"\n\t\t\tdndController=\"dijit.tree.dndSource\"\n\t\t\tbetweenThreshold=\"5\"\n\t\t\tmodel=\"feedModel\" openOnClick=\"false\">\n\t\t<script type=\"dojo/method\" event=\"onClick\" args=\"item\">\n\t\t\tvar id = String(item.id);\n\t\t\tvar bare_id = id.substr(id.indexOf(':')+1);\n\n\t\t\tif (id.match('FEED:')) {\n\t\t\t\teditFeed(bare_id);\n\t\t\t} else if (id.match('CAT:')) {\n\t\t\t\teditCat(bare_id, item);\n\t\t\t}\n\t\t</script>\n\t\t<script type=\"dojo/method\" event=\"onLoad\" args=\"item\">\n\t\t\tElement.hide(\"feedlistLoading\");\n\t\t</script>\n\t\t</div>";
    print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">\n\t\t\t" . __('<b>Hint:</b> you can drag feeds and categories around.') . "\n\t\t\t</div>";
    print '</div>';
    print '</div>';
    print "</div>";
    # feeds pane
    print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('OPML') . "\">";
    print "<p>" . __("Using OPML you can export and import your feeds and Tiny Tiny RSS settings.") . " ";
    print "<span class=\"insensitive\">" . __("Note: Only main settings profile can be migrated using OPML.") . "</span>";
    print "</p>";
    print "<h3>" . __("Import") . "</h3>";
    print "<br/><iframe id=\"upload_iframe\"\n\t\t\tname=\"upload_iframe\" onload=\"opmlImportComplete(this)\"\n\t\t\tstyle=\"width: 400px; height: 100px; display: none;\"></iframe>";
    print "<form  name=\"opml_form\" style='display : block' target=\"upload_iframe\"\n\t\t\tenctype=\"multipart/form-data\" method=\"POST\"\n\t\t\t\taction=\"backend.php\">\n\t\t\t<input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;\n\t\t\t<input type=\"hidden\" name=\"op\" value=\"dlg\">\n\t\t\t<input type=\"hidden\" name=\"id\" value=\"importOpml\">\n\t\t\t<button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" . __('Import') . "</button>";
    print "<h3>" . __("Export") . "</h3>";
    print "<p>" . __('Filename:') . " <input type=\"text\" id=\"filename\" value=\"TinyTinyRSS.opml\" />&nbsp;" . __('Include settings') . "<input type=\"checkbox\" id=\"settings\" CHECKED />" . "<button dojoType=\"dijit.form.Button\"\n\t\t\tonclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" . __('Export') . "</button></p></form>";
    print "<h3>" . __("Publish") . "</h3>";
    print "<p>" . __('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . " ";
    print "<span class=\"insensitive\">" . __("Note: Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.") . "</span>" . "</p>";
    print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('pubOPMLUrl')\">" . __('Display URL') . "</button> ";
    print "</div>";
    # pane
    if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
        print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Firefox integration') . "\">";
        print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>";
        print "<p>";
        print "<button onclick='window.navigator.registerContentHandler(" . "\"application/vnd.mozilla.maybe.feed\", " . "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" . __('Click here to register this site as a feed reader.') . "</button>";
        print "</p>";
        print "</div>";
        # pane
    }
    print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Subscribing using bookmarklet') . "\">";
    print "<p>" . __("Drag the link below to your browser toolbar, open the feed you're interested in in your browser and click on the link to subscribe to it.") . "</p>";
    $bm_subscribe_url = str_replace('%s', '', add_feed_url());
    $confirm_str = __('Subscribe to %s in Tiny Tiny RSS?');
    $bm_url = htmlspecialchars("javascript:{if(confirm('{$confirm_str}'.replace('%s',window.location.href)))window.location.href='{$bm_subscribe_url}'+window.location.href}");
    print "<a href=\"{$bm_url}\" class='bookmarklet'>" . __('Subscribe in Tiny Tiny RSS') . "</a>";
    print "</div>";
    #pane
    print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Published & shared articles and generated feeds') . "\">";
    print "<h3>" . __("Published articles and generated feeds") . "</h3>";
    print "<p>" . __('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.') . "</p>";
    $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() . "/public.php?op=rss&id=-2&view-mode=all_articles");
    print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('generatedFeed', '{$rss_url}')\">" . __('Display URL') . "</button> ";
    print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">" . __('Clear all generated URLs') . "</button> ";
    print "<h3>" . __("Articles shared by URL") . "</h3>";
    print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>";
    print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">" . __('Unshare all articles') . "</button> ";
    print "</div>";
    #pane
    if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
        print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"" . __('Twitter') . "\">";
        $result = db_query($link, "SELECT COUNT(*) AS cid FROM ttrss_users\n\t\t\t\tWHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND\n\t\t\t\tid = " . $_SESSION['uid']);
        $is_registered = db_fetch_result($result, 0, "cid") != 0;
        if (!$is_registered) {
            print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
        } else {
            print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
        }
        print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">" . __("Register with Twitter.com") . "</button>";
        print " ";
        print "<button dojoType=\"dijit.form.Button\"\n\t\t\t\tonclick=\"return clearTwitterCredentials()\">" . __("Clear stored credentials") . "</button>";
        print "</div>";
        # pane
    }
    print "</div>";
    #container
}