1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/ttrss_ynh.git synced 2024-10-01 13:34:46 +02:00

update ttrss 1.15.3

This commit is contained in:
Adrien Beudin 2015-01-22 17:56:46 +01:00
parent f6f84fd2b0
commit a335861ed5
36 changed files with 2260 additions and 1676 deletions

View file

@ -1,4 +1,4 @@
ttrss for YunoHost Tiny-Tiny RSS paquage for YunoHost
====================== ======================
http://tt-rss.org/redmine/projects/tt-rss/wiki http://tt-rss.org/redmine/projects/tt-rss/wiki

View file

@ -10,8 +10,9 @@ location PATHTOCHANGE {
fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php; fastcgi_index index.php;
include fastcgi_params; include fastcgi_params;
fastcgi_param REMOTE_USER $remote_user; fastcgi_param REMOTE_USER $remote_user;
fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $request_filename;
} }
# Include SSOWAT user panel. # Include SSOWAT user panel.

33
conf/ttrss.diff Normal file
View file

@ -0,0 +1,33 @@
--- update.php.ynh 2015-01-22 16:45:52.105737698 +0100
+++ update.php 2015-01-22 16:43:09.977745715 +0100
@@ -311,8 +311,8 @@
_debug("WARNING: please backup your database before continuing.");
_debug("Type 'yes' to continue.");
- //if (read_stdin() != 'yes')
- // exit;
+ if (read_stdin() != 'yes')
+ exit;
for ($i = $updater->getSchemaVersion() + 1; $i <= SCHEMA_VERSION; $i++) {
_debug("performing update up to version $i...");
--- plugins/auth_remote/init.php.ynh 2015-01-22 16:50:51.653723599 +0100
+++ plugins/auth_remote/init.php 2015-01-22 16:43:09.957745715 +0100
@@ -69,16 +69,6 @@
db_query("UPDATE ttrss_users SET email = '$email' WHERE id = " .
$user_id);
}
- // update user password to allow api access
- if (isset($_SERVER['PHP_AUTH_PW'])){
- $currentpassword = $_SERVER['PHP_AUTH_PW'];
- $new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
- $new_password_hash = encrypt_password($currentpassword, $new_salt, true);
-
- db_query("UPDATE ttrss_users SET
- pwd_hash = '$new_password_hash', salt = '$new_salt', otp_enabled = false
- WHERE login = '$try_login'");
- }
}
return $user_id;

View file

@ -5,16 +5,17 @@
"en": "A PHP and Ajax feed reader", "en": "A PHP and Ajax feed reader",
"fr": "Un lecteur de flux en PHP et Ajax" "fr": "Un lecteur de flux en PHP et Ajax"
}, },
"developer": { "url": "http://tt-rss.org",
"maintainer": {
"name": "titoko", "name": "titoko",
"email": "titoko@titoko.fr", "email": "titoko@titoko.fr"
"url": "http://dev.yunohost.org"
}, },
"multi_instance": "true", "multi_instance": "true",
"arguments": { "arguments": {
"install" : [ "install" : [
{ {
"name": "domain", "name": "domain",
"type": "domain",
"ask": { "ask": {
"en": "Choose a domain for Tiny-Tiny-RSS", "en": "Choose a domain for Tiny-Tiny-RSS",
"fr": "Choisissez un domaine pour Tiny-Tiny-RSS" "fr": "Choisissez un domaine pour Tiny-Tiny-RSS"
@ -23,6 +24,7 @@
}, },
{ {
"name": "path", "name": "path",
"type": "path",
"ask": { "ask": {
"en": "Choose a path for Tiny-Tiny-RSS", "en": "Choose a path for Tiny-Tiny-RSS",
"fr": "Choisissez un chemin pour Tiny-Tiny-RSS" "fr": "Choisissez un chemin pour Tiny-Tiny-RSS"

View file

@ -22,10 +22,13 @@ sudo yunohost app initdb $db_user -p $db_pwd -s $(readlink -e ../source/schema/T
sudo yunohost app setting ttrss mysqlpwd -v $db_pwd sudo yunohost app setting ttrss mysqlpwd -v $db_pwd
# Copy files to the right place # Copy files to the right place
final_path=/var/www/ttrss final_path=/var/www/ttrss
sudo mkdir -p $final_path sudo mkdir -p $final_path
sudo cp -r ../source/* $final_path sudo cp -r ../source/* $final_path
sudo cp ../conf/config.php $final_path/ sudo cp ../conf/config.php $final_path/
sudo cp ../conf/ttrss.diff $final_path/
sudo patch -p0 $final_path/ttrss.diff
# Change variables in ttrss configuration # Change variables in ttrss configuration
sudo sed -i "s/yunouser/$db_user/g" $final_path/config.php sudo sed -i "s/yunouser/$db_user/g" $final_path/config.php

View file

@ -5,15 +5,21 @@ path=$(sudo yunohost app setting ttrss path)
db_user=ttrss db_user=ttrss
db_pwd=$(sudo yunohost app setting ttrss mysqlpwd) db_pwd=$(sudo yunohost app setting ttrss mysqlpwd)
<<<<<<< HEAD
=======
#db_file=../source/schema/versions/mysql/$(ls -vr ../source/schema/versions/mysql | head -1) #db_file=../source/schema/versions/mysql/$(ls -vr ../source/schema/versions/mysql | head -1)
#mysql -u $db_user -p$db_pwd $db_user < $db_file #mysql -u $db_user -p$db_pwd $db_user < $db_file
>>>>>>> f6f84fd2b073b67a92eaed31b51016470a2e0d4e
final_path=/var/www/ttrss final_path=/var/www/ttrss
sudo mkdir -p $final_path sudo mkdir -p $final_path
sudo cp -a ../source/* $final_path sudo cp -a ../source/* $final_path
sudo cp ../conf/config.php $final_path/ sudo cp ../conf/config.php $final_path/
sudo cp ../conf/ttrss.diff $final_path/
sudo patch -p0 $final_path/ttrss.diff
# Change variables in ttrss configuration # Change variables in ttrss configuration
sudo sed -i "s/yunouser/$db_user/g" $final_path/config.php sudo sed -i "s/yunouser/$db_user/g" $final_path/config.php

View file

@ -2,7 +2,7 @@
class API extends Handler { class API extends Handler {
const API_LEVEL = 9; const API_LEVEL = 11;
const STATUS_OK = 0; const STATUS_OK = 0;
const STATUS_ERR = 1; const STATUS_ERR = 1;
@ -201,6 +201,10 @@ class API extends Handler {
$sanitize_content = !isset($_REQUEST["sanitize"]) || $sanitize_content = !isset($_REQUEST["sanitize"]) ||
sql_bool_to_bool($_REQUEST["sanitize"]); sql_bool_to_bool($_REQUEST["sanitize"]);
$force_update = sql_bool_to_bool($_REQUEST["force_update"]); $force_update = sql_bool_to_bool($_REQUEST["force_update"]);
$has_sandbox = sql_bool_to_bool($_REQUEST["has_sandbox"]);
$excerpt_length = (int)$this->dbh->escape_string($_REQUEST["excerpt_length"]);
$_SESSION['hasSandbox'] = $has_sandbox;
$override_order = false; $override_order = false;
switch ($_REQUEST["order_by"]) { switch ($_REQUEST["order_by"]) {
@ -223,7 +227,7 @@ class API extends Handler {
$headlines = $this->api_get_headlines($feed_id, $limit, $offset, $headlines = $this->api_get_headlines($feed_id, $limit, $offset,
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order, $filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order,
$include_attachments, $since_id, $search, $search_mode, $include_attachments, $since_id, $search, $search_mode,
$include_nested, $sanitize_content, $force_update); $include_nested, $sanitize_content, $force_update, $excerpt_length);
$this->wrap(self::STATUS_OK, $headlines); $this->wrap(self::STATUS_OK, $headlines);
} else { } else {
@ -633,7 +637,7 @@ class API extends Handler {
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order, $filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order,
$include_attachments, $since_id, $include_attachments, $since_id,
$search = "", $search_mode = "", $search = "", $search_mode = "",
$include_nested = false, $sanitize_content = true, $force_update = false) { $include_nested = false, $sanitize_content = true, $force_update = false, $excerpt_length = 100) {
if ($force_update && $feed_id > 0 && is_numeric($feed_id)) { if ($force_update && $feed_id > 0 && is_numeric($feed_id)) {
// Update the feed if required with some basic flood control // Update the feed if required with some basic flood control
@ -666,16 +670,31 @@ class API extends Handler {
$headlines = array(); $headlines = array();
while ($line = db_fetch_assoc($result)) { while ($line = db_fetch_assoc($result)) {
$line["content_preview"] = truncate_string(strip_tags($line["content"]), 100); $line["content_preview"] = truncate_string(strip_tags($line["content"]), $excerpt_length);
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) { foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
$line = $p->hook_query_headlines($line, 100, true); $line = $p->hook_query_headlines($line, $excerpt_length, true);
} }
$is_updated = ($line["last_read"] == "" && $is_updated = ($line["last_read"] == "" &&
($line["unread"] != "t" && $line["unread"] != "1")); ($line["unread"] != "t" && $line["unread"] != "1"));
$tags = explode(",", $line["tag_cache"]); $tags = explode(",", $line["tag_cache"]);
$labels = json_decode($line["label_cache"], true);
$label_cache = $line["label_cache"];
$labels = false;
if ($label_cache) {
$label_cache = json_decode($label_cache, true);
if ($label_cache) {
if ($label_cache["no-labels"] == 1)
$labels = array();
else
$labels = $label_cache;
}
}
if (!is_array($labels)) $labels = get_article_labels($line["id"]);
//if (!$tags) $tags = get_article_tags($line["id"]); //if (!$tags) $tags = get_article_tags($line["id"]);
//if (!$labels) $labels = get_article_labels($line["id"]); //if (!$labels) $labels = get_article_labels($line["id"]);

View file

@ -491,7 +491,9 @@ class Opml extends Handler_Protected {
if (is_file($tmp_file)) { if (is_file($tmp_file)) {
$doc = new DOMDocument(); $doc = new DOMDocument();
libxml_disable_entity_loader(false);
$doc->load($tmp_file); $doc->load($tmp_file);
libxml_disable_entity_loader(true);
unlink($tmp_file); unlink($tmp_file);
} else if (!$doc) { } else if (!$doc) {
print_error(__('Error: unable to find moved OPML file.')); print_error(__('Error: unable to find moved OPML file.'));

View file

@ -571,7 +571,8 @@ class Pref_Prefs extends Handler_Protected {
} else if ($pref_name == "USER_CSS_THEME") { } else if ($pref_name == "USER_CSS_THEME") {
$themes = array_map("basename", glob("themes/*.css")); $themes = array_filter(array_map("basename", glob("themes/*.css")),
"theme_valid");
print_select($pref_name, $value, $themes, print_select($pref_name, $value, $themes,
'dojoType="dijit.form.Select"'); 'dojoType="dijit.form.Select"');

View file

@ -93,6 +93,10 @@
background : white; background : white;
} }
.claro #feedTree.dijitTree .dijitTreeRowSelected {
box-shadow : -1px 0px 2px -1px rgba(0,0,0,0.1);
}
.claro .dijitTree .dijitTreeRowHover { .claro .dijitTree .dijitTreeRowHover {
background : #f0f0f0; background : #f0f0f0;
border-color : #ddd; border-color : #ddd;

View file

@ -7,6 +7,11 @@ body#ttrssMain, body#ttrssPrefs, body#ttrssLogin, body {
font-size: 14px; font-size: 14px;
} }
body#ttrssMain {
overflow : hidden;
max-height : 100%;
}
div.postReply { div.postReply {
padding : 0px; padding : 0px;
} }
@ -138,18 +143,30 @@ a:hover {
position : absolute; position : absolute;
} }
#notify.visible {
transform: translate(0, -35px);
-webkit-transform: translate(0, -35px);
-o-transform: translate(0, -35px);
-moz-transform: translate(0, -35px);
}
#notify { #notify {
bottom : 10px; bottom : -35px;
right : 20px; right : 0px;
border-width : 1px; height : 20px;
left : 0px;
border-width : 1px 0px 0px 0px;
border-style : solid; border-style : solid;
position : absolute; position : fixed;
font-size : 12px; font-size : 12px;
z-index : 99; z-index : 99;
max-width : 200px;
min-width : 100px;
padding : 5px; padding : 5px;
-width : 200px; box-shadow : 0px -2px 2px rgba(0,0,0,0.1);
transition: all 0.5s ease-in-out;
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
} }
#notify img { #notify img {
@ -176,17 +193,17 @@ a:hover {
background-color : #fff7d5; background-color : #fff7d5;
} }
.notify.progress { .notify.notify_progress {
border-color : #d7c47a; border-color : #d7c47a;
background-color : #fff7d5; background-color : #fff7d5;
} }
.notify.info { .notify.notify_info {
border-color : #88b0f0; border-color : #88b0f0;
background-color : #ecf4ff; background-color : #ecf4ff;
} }
.notify.error { .notify.notify_error {
background-color : #ffcccc; background-color : #ffcccc;
border-color : #ff0000; border-color : #ff0000;
} }
@ -796,7 +813,7 @@ div.fatalError textarea {
#feeds-holder { #feeds-holder {
padding : 0px; padding : 0px;
border-width : 0px 1px 0px 0px; border-width : 0px 0px 0px 0px;
border-style : solid; border-style : solid;
border-color : #ddd; border-color : #ddd;
overflow : hidden; overflow : hidden;

View file

@ -14,6 +14,8 @@
$fetch_curl_used = false; $fetch_curl_used = false;
$suppress_debugging = false; $suppress_debugging = false;
libxml_disable_entity_loader(true);
mb_internal_encoding("UTF-8"); mb_internal_encoding("UTF-8");
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
if (defined('E_DEPRECATED')) { if (defined('E_DEPRECATED')) {
@ -357,6 +359,9 @@
$url = ltrim($url, ' '); $url = ltrim($url, ' ');
$url = str_replace(' ', '%20', $url); $url = str_replace(' ', '%20', $url);
if (strpos($url, "//") === 0)
$url = 'http:' . $url;
if (!defined('NO_CURL') && function_exists('curl_init')) { if (!defined('NO_CURL') && function_exists('curl_init')) {
$fetch_curl_used = true; $fetch_curl_used = true;

View file

@ -17,7 +17,10 @@
$params["default_view_order_by"] = get_pref("_DEFAULT_VIEW_ORDER_BY"); $params["default_view_order_by"] = get_pref("_DEFAULT_VIEW_ORDER_BY");
$params["bw_limit"] = (int) $_SESSION["bw_limit"]; $params["bw_limit"] = (int) $_SESSION["bw_limit"];
$params["label_base_index"] = (int) LABEL_BASE_INDEX; $params["label_base_index"] = (int) LABEL_BASE_INDEX;
$params["theme"] = get_pref("USER_CSS_THEME", false, false);
$theme = get_pref( "USER_CSS_THEME", false, false);
$params["theme"] = theme_valid("$theme") ? $theme : "";
$params["plugins"] = implode(", ", PluginHost::getInstance()->get_plugin_names()); $params["plugins"] = implode(", ", PluginHost::getInstance()->get_plugin_names());
$params["php_platform"] = PHP_OS; $params["php_platform"] = PHP_OS;
@ -826,6 +829,21 @@
} }
function iframe_whitelisted($entry) {
$whitelist = array("youtube.com", "youtu.be", "vimeo.com");
@$src = parse_url($entry->getAttribute("src"), PHP_URL_HOST);
if ($src) {
foreach ($whitelist as $w) {
if ($src == $w || $src == "www.$w")
return true;
}
}
return false;
}
function sanitize($str, $force_remove_images = false, $owner = false, $site_url = false, $highlight_words = false, $article_id = false) { function sanitize($str, $force_remove_images = false, $owner = false, $site_url = false, $highlight_words = false, $article_id = false) {
if (!$owner) $owner = $_SESSION["uid"]; if (!$owner) $owner = $_SESSION["uid"];
@ -894,8 +912,15 @@
$entries = $xpath->query('//iframe'); $entries = $xpath->query('//iframe');
foreach ($entries as $entry) { foreach ($entries as $entry) {
$entry->setAttribute('sandbox', 'allow-scripts'); if (!iframe_whitelisted($entry)) {
$entry->setAttribute('sandbox', 'allow-scripts');
} else {
if ($_SERVER['HTTPS'] == "on") {
$entry->setAttribute("src",
str_replace("http://", "https://",
$entry->getAttribute("src")));
}
}
} }
$allowed_elements = array('a', 'address', 'audio', 'article', 'aside', $allowed_elements = array('a', 'address', 'audio', 'article', 'aside',
@ -1958,8 +1983,8 @@
} }
function getLastArticleId() { function getLastArticleId() {
$result = db_query("SELECT MAX(ref_id) AS id FROM ttrss_user_entries $result = db_query("SELECT ref_id AS id FROM ttrss_user_entries
WHERE owner_uid = " . $_SESSION["uid"]); WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY ref_id DESC LIMIT 1");
if (db_num_rows($result) == 1) { if (db_num_rows($result) == 1) {
return db_fetch_result($result, 0, "id"); return db_fetch_result($result, 0, "id");
@ -2400,4 +2425,21 @@
return LABEL_BASE_INDEX - 1 + abs($feed); return LABEL_BASE_INDEX - 1 + abs($feed);
} }
function theme_valid($file) {
if ($file == "default.css" || $file == "night.css") return true; // needed for array_filter
$file = "themes/" . basename($file);
if (file_exists($file) && is_readable($file)) {
$fh = fopen($file, "r");
if ($fh) {
$header = fgets($fh);
fclose($fh);
return strpos($header, "supports-version:" . VERSION_STATIC) !== FALSE;
}
}
return false;
}
?> ?>

View file

@ -481,7 +481,7 @@
if (!$registered_title || $registered_title == "[Unknown]") { if (!$registered_title || $registered_title == "[Unknown]") {
$feed_title = db_escape_string($rss->get_title()); $feed_title = db_escape_string(mb_substr($rss->get_title(), 0, 199));
if ($feed_title) { if ($feed_title) {
_debug("registering title: $feed_title", $debug_enabled); _debug("registering title: $feed_title", $debug_enabled);
@ -707,7 +707,11 @@
db_query("UPDATE ttrss_entries SET date_updated = NOW() db_query("UPDATE ttrss_entries SET date_updated = NOW()
WHERE id = '$base_entry_id'"); WHERE id = '$base_entry_id'");
continue; // 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); _debug("hash differs, applying plugin filters:", $debug_enabled);

View file

@ -1,5 +1,5 @@
<?php <?php
define('VERSION_STATIC', '1.14'); define('VERSION_STATIC', '1.15.3');
function get_version() { function get_version() {
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');

View file

@ -65,7 +65,7 @@
<?php if ($_SESSION["uid"]) { <?php if ($_SESSION["uid"]) {
$theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false); $theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false);
if ($theme && file_exists("themes/$theme")) { if ($theme && theme_valid("$theme")) {
echo stylesheet_tag("themes/$theme"); echo stylesheet_tag("themes/$theme");
} else { } else {
echo stylesheet_tag("themes/default.css"); echo stylesheet_tag("themes/default.css");
@ -138,7 +138,7 @@
</div> </div>
</div> </div>
<div id="notify" class="notify" style="display : none"></div> <div id="notify" class="notify"></div>
<div id="cmdline" style="display : none"></div> <div id="cmdline" style="display : none"></div>
<div id="headlines-tmp" style="display : none"></div> <div id="headlines-tmp" style="display : none"></div>

View file

@ -182,11 +182,6 @@ function param_unescape(arg) {
return unescape(arg); return unescape(arg);
} }
function hide_notify() {
Element.hide('notify');
}
function notify_real(msg, no_hide, n_type) { function notify_real(msg, no_hide, n_type) {
var n = $("notify"); var n = $("notify");
@ -198,13 +193,11 @@ function notify_real(msg, no_hide, n_type) {
} }
if (msg == "") { if (msg == "") {
if (Element.visible(n)) { if (n.hasClassName("visible")) {
notify_hide_timerid = window.setTimeout("hide_notify()", 0); notify_hide_timerid = window.setTimeout(function() {
n.removeClassName("visible") }, 0);
} }
return; return;
} else {
Element.show(n);
new Effect.Highlight(n);
} }
/* types: /* types:
@ -218,30 +211,40 @@ function notify_real(msg, no_hide, n_type) {
msg = "<span class=\"msg\"> " + __(msg) + "</span>"; msg = "<span class=\"msg\"> " + __(msg) + "</span>";
if (n_type == 1) { if (n_type == 2) {
n.className = "notify";
} else if (n_type == 2) {
n.className = "notify progress";
msg = "<span><img src='images/indicator_white.gif'></span>" + msg; msg = "<span><img src='images/indicator_white.gif'></span>" + msg;
no_hide = true; no_hide = true;
} else if (n_type == 3) { } else if (n_type == 3) {
n.className = "notify error";
msg = "<span><img src='images/alert.png'></span>" + msg; msg = "<span><img src='images/alert.png'></span>" + msg;
} else if (n_type == 4) { } else if (n_type == 4) {
n.className = "notify info";
msg = "<span><img src='images/information.png'></span>" + msg; msg = "<span><img src='images/information.png'></span>" + msg;
} }
msg += " <span><img src=\"images/cross.png\" class=\"close\" title=\"" + msg += " <span><img src=\"images/cross.png\" class=\"close\" title=\"" +
__("Click to close") + "\" onclick=\"notify('')\"></span>"; __("Click to close") + "\" onclick=\"notify('')\"></span>";
// msg = "<img src='images/live_com_loading.gif'> " + msg;
n.innerHTML = msg; n.innerHTML = msg;
if (!no_hide) { window.setTimeout(function() {
notify_hide_timerid = window.setTimeout("hide_notify()", 5*1000); // goddamnit firefox
} if (n_type == 2) {
n.className = "notify notify_progress visible";
} else if (n_type == 3) {
n.className = "notify notify_error visible";
msg = "<span><img src='images/alert.png'></span>" + msg;
} else if (n_type == 4) {
n.className = "notify notify_info visible";
} else {
n.className = "notify visible";
}
if (!no_hide) {
notify_hide_timerid = window.setTimeout(function() {
n.removeClassName("visible") }, 5*1000);
}
}, 10);
} }
function notify(msg, no_hide) { function notify(msg, no_hide) {

View file

@ -302,21 +302,27 @@ function init() {
hotkey_actions["collapse_article"] = function() { hotkey_actions["collapse_article"] = function() {
var id = getActiveArticleId(); var id = getActiveArticleId();
var elem = $("CICD-"+id); var elem = $("CICD-"+id);
if(elem.visible()) {
cdmCollapseArticle(null, id); if (elem) {
} if (elem.visible()) {
else { cdmCollapseArticle(null, id);
cdmExpandArticle(id); }
else {
cdmExpandArticle(id);
}
} }
}; };
hotkey_actions["toggle_expand"] = function() { hotkey_actions["toggle_expand"] = function() {
var id = getActiveArticleId(); var id = getActiveArticleId();
var elem = $("CICD-"+id); var elem = $("CICD-"+id);
if(elem.visible()) {
cdmCollapseArticle(null, id, false); if (elem) {
} if (elem.visible()) {
else { cdmCollapseArticle(null, id, false);
cdmExpandArticle(id); }
else {
cdmExpandArticle(id);
}
} }
}; };
hotkey_actions["search_dialog"] = function() { hotkey_actions["search_dialog"] = function() {

View file

@ -12,8 +12,8 @@ msgstr ""
"Project-Id-Version: Tiny Tiny RSS\n" "Project-Id-Version: Tiny Tiny RSS\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-09-06 15:10+0400\n" "POT-Creation-Date: 2014-09-06 15:10+0400\n"
"PO-Revision-Date: 2014-09-06 20:33+0100\n" "PO-Revision-Date: 2014-11-19 18:13+0100\n"
"Last-Translator: Heiko Adams <heiko.adams@gmai.com>\n" "Last-Translator: Robert Wetzlmayr <r.wetzlmayr@gmail.com>\n"
"Language-Team: \n" "Language-Team: \n"
"Language: de\n" "Language: de\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -21,7 +21,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-Bookmarks: -1,557,558,-1,-1,-1,-1,-1,-1,-1\n" "X-Poedit-Bookmarks: -1,557,558,-1,-1,-1,-1,-1,-1,-1\n"
"X-Generator: Poedit 1.5.4\n" "X-Generator: Poedit 1.5.5\n"
#: backend.php:73 #: backend.php:73
msgid "Use default" msgid "Use default"
@ -1771,7 +1771,7 @@ msgstr "Maximales Alter neuer Artikel (in Stunden)"
#: classes/pref/prefs.php:41 #: classes/pref/prefs.php:41
msgid "Hide feeds with no unread articles" msgid "Hide feeds with no unread articles"
msgstr "Feeds ohne unglesene Nachrichten verbergen" msgstr "Feeds ohne ungelesene Nachrichten verbergen"
#: classes/pref/prefs.php:42 #: classes/pref/prefs.php:42
msgid "Show special feeds when hiding read feeds" msgid "Show special feeds when hiding read feeds"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -6,23 +6,33 @@ class Af_Comics_Dilbert extends Af_ComicFilter {
} }
function process(&$article) { function process(&$article) {
$owner_uid = $article["owner_uid"];
if (strpos($article["guid"], "dilbert.com") !== FALSE) { if (strpos($article["guid"], "dilbert.com") !== FALSE) {
$res = fetch_file_contents($article["link"], false, false, false,
false, false, 0,
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
global $fetch_last_error_content;
if (!$res && $fetch_last_error_content)
$res = $fetch_last_error_content;
$doc = new DOMDocument(); $doc = new DOMDocument();
@$doc->loadHTML(fetch_file_contents($article["link"])); @$doc->loadHTML($res);
$basenode = false; $basenode = false;
if ($doc) { if ($doc) {
$xpath = new DOMXPath($doc); $xpath = new DOMXPath($doc);
$entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
$basenode = $xpath->query('//div[@class="STR_Image"]')->item(0);
/* $entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
$matches = array(); $matches = array();
foreach ($entries as $entry) { foreach ($entries as $entry) {
if (preg_match("/dyn\/str_strip\/.*zoom\.gif$/", $entry->getAttribute("src"), $matches)) { if (preg_match("/dyn\/str_strip\/.*strip\.gif$/", $entry->getAttribute("src"), $matches)) {
$entry->setAttribute("src", $entry->setAttribute("src",
rewrite_relative_url("http://dilbert.com/", rewrite_relative_url("http://dilbert.com/",
@ -31,7 +41,7 @@ class Af_Comics_Dilbert extends Af_ComicFilter {
$basenode = $entry; $basenode = $entry;
break; break;
} }
} } */
if ($basenode) { if ($basenode) {
$article["content"] = $doc->saveXML($basenode); $article["content"] = $doc->saveXML($basenode);

View file

@ -56,7 +56,9 @@ class Af_Comics_Pa extends Af_ComicFilter {
if ($header->parentNode) { $header->parentNode->removeChild($header); } if ($header->parentNode) { $header->parentNode->removeChild($header); }
$avatar = $xpath->query('(//div[@class="avatar"]//img)')->item(0); $avatar = $xpath->query('(//div[@class="avatar"]//img)')->item(0);
$basenode->insertBefore($avatar, $basenode->firstChild);
if ($basenode)
$basenode->insertBefore($avatar, $basenode->firstChild);
$uninteresting = $xpath->query('(//div[@class="avatar"])'); $uninteresting = $xpath->query('(//div[@class="avatar"])');
foreach ($uninteresting as $i) { foreach ($uninteresting as $i) {

View file

@ -0,0 +1,32 @@
<?php
class Af_Comics_Tfd extends Af_ComicFilter {
function supported() {
return array("Toothpaste For Dinner");
}
function process(&$article) {
$owner_uid = $article["owner_uid"];
if (strpos($article["link"], "toothpastefordinner.com") !== FALSE) {
$doc = new DOMDocument();
@$doc->loadHTML(fetch_file_contents($article["link"]));
$basenode = false;
if ($doc) {
$xpath = new DOMXPath($doc);
$basenode = $xpath->query('//img[@class="comic"]')->item(0);
if ($basenode) {
$article["content"] = $doc->saveXML($basenode);
return true;
}
}
}
return false;
}
}
?>

View file

@ -0,0 +1,79 @@
<?php
class Af_Tumblr_1280 extends Plugin {
private $host;
function about() {
return array(1.0,
"Replace Tumblr pictures with largest size if available",
"fox");
}
function init($host) {
$this->host = $host;
if (function_exists("curl_init")) {
$host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
}
}
function hook_article_filter($article) {
$owner_uid = $article["owner_uid"];
$charset_hack = '<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>';
$doc = new DOMDocument();
$doc->loadHTML($charset_hack . $article["content"]);
$found = false;
if ($doc) {
$xpath = new DOMXpath($doc);
$images = $xpath->query('(//img[contains(@src, \'media.tumblr.com\')])');
foreach ($images as $img) {
$src = $img->getAttribute("src");
$test_src = preg_replace("/_\d{3}.(jpg|gif|png)/", "_1280.$1", $src);
if ($src != $test_src) {
$ch = curl_init($test_src);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,
!ini_get("safe_mode") && !ini_get("open_basedir"));
curl_setopt($ch, CURLOPT_USERAGENT, SELF_USER_AGENT);
@$result = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($result && $http_code == 200) {
$img->setAttribute("src", $test_src);
$found = true;
}
}
}
if ($found) {
$doc->removeChild($doc->firstChild); //remove doctype
$article["content"] = $doc->saveHTML();
}
}
return $article;
}
function api_version() {
return 2;
}
}
?>

View file

@ -0,0 +1,88 @@
<?php
class Af_Zz_ImgSetSizes extends Plugin {
private $host;
function about() {
return array(1.0,
"Set width/height attributes for images in articles (requires CURL and GD)",
"fox");
}
function init($host) {
$this->host = $host;
if (function_exists("curl_init") && function_exists("getimagesize")) {
$host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
}
}
function hook_article_filter($article) {
$owner_uid = $article["owner_uid"];
$charset_hack = '<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>';
$doc = new DOMDocument();
$doc->loadHTML($charset_hack . $article["content"]);
$found = false;
if ($doc) {
$xpath = new DOMXpath($doc);
$images = $xpath->query('(//img[@src])');
foreach ($images as $img) {
$src = $img->getAttribute("src");
$ch = curl_init($src);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch, CURLOPT_RANGE, "0-32768");
@$result = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($result && ($http_code == 200 || $http_code == 206)) {
$filename = tempnam(sys_get_temp_dir(), "ttsizecheck");
if ($filename) {
$fh = fopen($filename, "w");
if ($fh) {
fwrite($fh, $result);
fclose($fh);
@$info = getimagesize($filename);
if ($info && $info[0] > 0 && $info[1] > 0) {
$img->setAttribute("width", $info[0]);
$img->setAttribute("height", $info[1]);
$found = true;
}
unlink($filename);
}
}
}
}
if ($found) {
$doc->removeChild($doc->firstChild); //remove doctype
$article["content"] = $doc->saveHTML();
}
}
return $article;
}
function api_version() {
return 2;
}
}
?>

View file

@ -69,16 +69,6 @@ class Auth_Remote extends Plugin implements IAuthModule {
db_query("UPDATE ttrss_users SET email = '$email' WHERE id = " . db_query("UPDATE ttrss_users SET email = '$email' WHERE id = " .
$user_id); $user_id);
} }
// update user password to allow api access
if (isset($_SERVER['PHP_AUTH_PW'])){
$currentpassword = $_SERVER['PHP_AUTH_PW'];
$new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
$new_password_hash = encrypt_password($currentpassword, $new_salt, true);
db_query("UPDATE ttrss_users SET
pwd_hash = '$new_password_hash', salt = '$new_salt', otp_enabled = false
WHERE login = '$try_login'");
}
} }
return $user_id; return $user_id;

View file

@ -0,0 +1,97 @@
<?php
class Auth_Remote extends Plugin implements IAuthModule {
private $host;
private $base;
function about() {
return array(1.0,
"Authenticates against remote password (e.g. supplied by Apache)",
"fox",
true);
}
function init($host) {
$this->host = $host;
$this->base = new Auth_Base();
$host->add_hook($host::HOOK_AUTH_USER, $this);
}
function get_login_by_ssl_certificate() {
$cert_serial = db_escape_string(get_ssl_certificate_id());
if ($cert_serial) {
$result = db_query("SELECT login FROM ttrss_user_prefs, ttrss_users
WHERE pref_name = 'SSL_CERT_SERIAL' AND value = '$cert_serial' AND
owner_uid = ttrss_users.id");
if (db_num_rows($result) != 0) {
return db_escape_string(db_fetch_result($result, 0, "login"));
}
}
return "";
}
function authenticate($login, $password) {
$try_login = db_escape_string($_SERVER["REMOTE_USER"]);
// php-cgi
if (!$try_login) $try_login = db_escape_string($_SERVER["REDIRECT_REMOTE_USER"]);
if (!$try_login) $try_login = $this->get_login_by_ssl_certificate();
# if (!$try_login) $try_login = "test_qqq";
if ($try_login) {
$user_id = $this->base->auto_create_user($try_login, $password);
if ($user_id) {
$_SESSION["fake_login"] = $try_login;
$_SESSION["fake_password"] = "******";
$_SESSION["hide_hello"] = true;
$_SESSION["hide_logout"] = true;
// LemonLDAP can send user informations via HTTP HEADER
if (defined('AUTH_AUTO_CREATE') && AUTH_AUTO_CREATE){
// update user name
$fullname = $_SERVER['HTTP_USER_NAME'] ? $_SERVER['HTTP_USER_NAME'] : $_SERVER['AUTHENTICATE_CN'];
if ($fullname){
$fullname = db_escape_string($fullname);
db_query("UPDATE ttrss_users SET full_name = '$fullname' WHERE id = " .
$user_id);
}
// update user mail
$email = $_SERVER['HTTP_USER_MAIL'] ? $_SERVER['HTTP_USER_MAIL'] : $_SERVER['AUTHENTICATE_MAIL'];
if ($email){
$email = db_escape_string($email);
db_query("UPDATE ttrss_users SET email = '$email' WHERE id = " .
$user_id);
}
// update user password to allow api access
if (isset($_SERVER['PHP_AUTH_PW'])){
$currentpassword = $_SERVER['PHP_AUTH_PW'];
$new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
$new_password_hash = encrypt_password($currentpassword, $new_salt, true);
db_query("UPDATE ttrss_users SET
pwd_hash = '$new_password_hash', salt = '$new_salt', otp_enabled = false
WHERE login = '$try_login'");
}
}
return $user_id;
}
}
return false;
}
function api_version() {
return 2;
}
}
?>

View file

@ -4,7 +4,7 @@ class No_Iframes extends Plugin {
function about() { function about() {
return array(1.0, return array(1.0,
"Remove embedded iframes", "Remove embedded iframes (unless whitelisted)",
"fox"); "fox");
} }
@ -16,7 +16,13 @@ class No_Iframes extends Plugin {
function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes) { function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes) {
$allowed_elements = array_diff($allowed_elements, array("iframe")); $xpath = new DOMXpath($doc);
$entries = $xpath->query('//iframe');
foreach ($entries as $entry) {
if (!iframe_whitelisted($entry))
$entry->parentNode->removeChild($entry);
}
return array($doc, $allowed_elements, $disallowed_attributes); return array($doc, $allowed_elements, $disallowed_attributes);
} }

View file

@ -41,7 +41,7 @@
<?php if ($_SESSION["uid"]) { <?php if ($_SESSION["uid"]) {
$theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false); $theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false);
if ($theme && file_exists("themes/$theme")) { if ($theme && theme_valid("$theme")) {
echo stylesheet_tag("themes/$theme"); echo stylesheet_tag("themes/$theme");
} else { } else {
echo stylesheet_tag("themes/default.css"); echo stylesheet_tag("themes/default.css");
@ -94,7 +94,7 @@
<body id="ttrssPrefs" class="claro"> <body id="ttrssPrefs" class="claro">
<div id="notify" class="notify" style="display : none"></div> <div id="notify" class="notify"></div>
<div id="cmdline" style="display : none"></div> <div id="cmdline" style="display : none"></div>
<div id="overlay"> <div id="overlay">

View file

@ -44,7 +44,6 @@ create table ttrss_users (id integer primary key not null auto_increment,
pwd_hash varchar(250) not null, pwd_hash varchar(250) not null,
last_login datetime default null, last_login datetime default null,
access_level integer not null default 0, access_level integer not null default 0,
theme_id integer default null,
email varchar(250) not null default '', email varchar(250) not null default '',
full_name varchar(250) not null default '', full_name varchar(250) not null default '',
email_digest bool not null default false, email_digest bool not null default false,
@ -53,7 +52,7 @@ create table ttrss_users (id integer primary key not null auto_increment,
created datetime default null, created datetime default null,
twitter_oauth longtext default null, twitter_oauth longtext default null,
otp_enabled boolean not null default false, otp_enabled boolean not null default false,
index (theme_id)) ENGINE=InnoDB DEFAULT CHARSET=UTF8; resetpass_token varchar(250) default null) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
insert into ttrss_users (login,pwd_hash,access_level) values ('admin', insert into ttrss_users (login,pwd_hash,access_level) values ('admin',
'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', 10); 'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', 10);
@ -302,7 +301,7 @@ create table ttrss_tags (id integer primary key auto_increment,
create table ttrss_version (schema_version int not null) ENGINE=InnoDB DEFAULT CHARSET=UTF8; create table ttrss_version (schema_version int not null) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
insert into ttrss_version values (123); insert into ttrss_version values (126);
create table ttrss_enclosures (id integer primary key auto_increment, create table ttrss_enclosures (id integer primary key auto_increment,
content_url text not null, content_url text not null,
@ -310,6 +309,8 @@ create table ttrss_enclosures (id integer primary key auto_increment,
post_id integer not null, post_id integer not null,
title text not null, title text not null,
duration text not null, duration text not null,
width integer not null default 0,
height integer not null default 0,
index (post_id), index (post_id),
foreign key (post_id) references ttrss_entries(id) ON DELETE cascade) ENGINE=InnoDB DEFAULT CHARSET=UTF8; foreign key (post_id) references ttrss_entries(id) ON DELETE cascade) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

View file

@ -3,12 +3,17 @@
body#ttrssMain #feeds-holder { body#ttrssMain #feeds-holder {
background : #222; background : #222;
border-color : #666; border-color : #666;
border-left-width : 1px;
} }
body#ttrssMain #headlines-frame { body#ttrssMain #headlines-frame {
border-color : #ddd; border-color : #ddd;
} }
body#ttrssMain div.whiteBox {
border-color : #666;
}
body#ttrssMain #content-insert { body#ttrssMain #content-insert {
background : #333; background : #333;
} }
@ -132,6 +137,7 @@ body#ttrssMain #feedTree img,
body#ttrssMain .postContent img { body#ttrssMain .postContent img {
filter: grayscale(1); filter: grayscale(1);
-webkit-filter: grayscale(1); -webkit-filter: grayscale(1);
filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale"); // firefox lol
} }
body#ttrssMain .hl img.hlScorePic { body#ttrssMain .hl img.hlScorePic {

359
source/update.php.ynh Executable file
View file

@ -0,0 +1,359 @@
#!/usr/bin/env php
<?php
set_include_path(dirname(__FILE__) ."/include" . PATH_SEPARATOR .
get_include_path());
define('DISABLE_SESSIONS', true);
chdir(dirname(__FILE__));
require_once "autoload.php";
require_once "functions.php";
require_once "rssfuncs.php";
require_once "config.php";
require_once "sanity_check.php";
require_once "db.php";
require_once "db-prefs.php";
if (!defined('PHP_EXECUTABLE'))
define('PHP_EXECUTABLE', '/usr/bin/php');
init_plugins();
$longopts = array("feeds",
"feedbrowser",
"daemon",
"daemon-loop",
"task:",
"cleanup-tags",
"quiet",
"log:",
"indexes",
"pidlock:",
"update-schema",
"convert-filters",
"force-update",
"list-plugins",
"help");
foreach (PluginHost::getInstance()->get_commands() as $command => $data) {
array_push($longopts, $command . $data["suffix"]);
}
$options = getopt("", $longopts);
if (!is_array($options)) {
die("error: getopt() failed. ".
"Most probably you are using PHP CGI to run this script ".
"instead of required PHP CLI. Check tt-rss wiki page on updating feeds for ".
"additional information.\n");
}
if (count($options) == 0 && !defined('STDIN')) {
?> <html>
<head>
<title>Tiny Tiny RSS data update script.</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="css/utility.css">
</head>
<body>
<div class="floatingLogo"><img src="images/logo_small.png"></div>
<h1><?php echo __("Tiny Tiny RSS data update script.") ?></h1>
<?php print_error("Please run this script from the command line. Use option \"-help\" to display command help if this error is displayed erroneously."); ?>
</body></html>
<?php
exit;
}
if (count($options) == 0 || isset($options["help"]) ) {
print "Tiny Tiny RSS data update script.\n\n";
print "Options:\n";
print " --feeds - update feeds\n";
print " --feedbrowser - update feedbrowser\n";
print " --daemon - start single-process update daemon\n";
print " --task N - create lockfile using this task id\n";
print " --cleanup-tags - perform tags table maintenance\n";
print " --quiet - don't output messages to stdout\n";
print " --log FILE - log messages to FILE\n";
print " --indexes - recreate missing schema indexes\n";
print " --update-schema - update database schema\n";
print " --convert-filters - convert type1 filters to type2\n";
print " --force-update - force update of all feeds\n";
print " --list-plugins - list all available plugins\n";
print " --help - show this help\n";
print "Plugin options:\n";
foreach (PluginHost::getInstance()->get_commands() as $command => $data) {
$args = $data['arghelp'];
printf(" --%-19s - %s\n", "$command $args", $data["description"]);
}
return;
}
if (!isset($options['daemon'])) {
require_once "errorhandler.php";
}
if (!isset($options['update-schema'])) {
$schema_version = get_schema_version();
if ($schema_version != SCHEMA_VERSION) {
die("Schema version is wrong, please upgrade the database.\n");
}
}
define('QUIET', isset($options['quiet']));
if (isset($options["log"])) {
_debug("Logging to " . $options["log"]);
define('LOGFILE', $options["log"]);
}
if (!isset($options["daemon"])) {
$lock_filename = "update.lock";
} else {
$lock_filename = "update_daemon.lock";
}
if (isset($options["task"])) {
_debug("Using task id " . $options["task"]);
$lock_filename = $lock_filename . "-task_" . $options["task"];
}
if (isset($options["pidlock"])) {
$my_pid = $options["pidlock"];
$lock_filename = "update_daemon-$my_pid.lock";
}
_debug("Lock: $lock_filename");
$lock_handle = make_lockfile($lock_filename);
$must_exit = false;
if (isset($options["task"]) && isset($options["pidlock"])) {
$waits = $options["task"] * 5;
_debug("Waiting before update ($waits)");
sleep($waits);
}
// Try to lock a file in order to avoid concurrent update.
if (!$lock_handle) {
die("error: Can't create lockfile ($lock_filename). ".
"Maybe another update process is already running.\n");
}
if (isset($options["force-update"])) {
_debug("marking all feeds as needing update...");
db_query( "UPDATE ttrss_feeds SET last_update_started = '1970-01-01',
last_updated = '1970-01-01'");
}
if (isset($options["feeds"])) {
update_daemon_common();
housekeeping_common(true);
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", $op);
}
if (isset($options["feedbrowser"])) {
$count = update_feedbrowser_cache();
print "Finished, $count feeds processed.\n";
}
if (isset($options["daemon"])) {
while (true) {
$quiet = (isset($options["quiet"])) ? "--quiet" : "";
$log = isset($options['log']) ? '--log '.$options['log'] : '';
passthru(PHP_EXECUTABLE . " " . $argv[0] ." --daemon-loop $quiet $log");
_debug("Sleeping for " . DAEMON_SLEEP_INTERVAL . " seconds...");
sleep(DAEMON_SLEEP_INTERVAL);
}
}
if (isset($options["daemon-loop"])) {
if (!make_stampfile('update_daemon.stamp')) {
_debug("warning: unable to create stampfile\n");
}
update_daemon_common(isset($options["pidlock"]) ? 50 : DAEMON_FEED_LIMIT);
if (!isset($options["pidlock"]) || $options["task"] == 0)
housekeeping_common(true);
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", $op);
}
if (isset($options["cleanup-tags"])) {
$rc = cleanup_tags( 14, 50000);
_debug("$rc tags deleted.\n");
}
if (isset($options["indexes"])) {
_debug("PLEASE BACKUP YOUR DATABASE BEFORE PROCEEDING!");
_debug("Type 'yes' to continue.");
if (read_stdin() != 'yes')
exit;
_debug("clearing existing indexes...");
if (DB_TYPE == "pgsql") {
$result = db_query( "SELECT relname FROM
pg_catalog.pg_class WHERE relname LIKE 'ttrss_%'
AND relname NOT LIKE '%_pkey'
AND relkind = 'i'");
} else {
$result = db_query( "SELECT index_name,table_name FROM
information_schema.statistics WHERE index_name LIKE 'ttrss_%'");
}
while ($line = db_fetch_assoc($result)) {
if (DB_TYPE == "pgsql") {
$statement = "DROP INDEX " . $line["relname"];
_debug($statement);
} else {
$statement = "ALTER TABLE ".
$line['table_name']." DROP INDEX ".$line['index_name'];
_debug($statement);
}
db_query( $statement, false);
}
_debug("reading indexes from schema for: " . DB_TYPE);
$fp = fopen("schema/ttrss_schema_" . DB_TYPE . ".sql", "r");
if ($fp) {
while ($line = fgets($fp)) {
$matches = array();
if (preg_match("/^create index ([^ ]+) on ([^ ]+)$/i", $line, $matches)) {
$index = $matches[1];
$table = $matches[2];
$statement = "CREATE INDEX $index ON $table";
_debug($statement);
db_query( $statement);
}
}
fclose($fp);
} else {
_debug("unable to open schema file.");
}
_debug("all done.");
}
if (isset($options["convert-filters"])) {
_debug("WARNING: this will remove all existing type2 filters.");
_debug("Type 'yes' to continue.");
if (read_stdin() != 'yes')
exit;
_debug("converting filters...");
db_query( "DELETE FROM ttrss_filters2");
$result = db_query( "SELECT * FROM ttrss_filters ORDER BY id");
while ($line = db_fetch_assoc($result)) {
$owner_uid = $line["owner_uid"];
// date filters are removed
if ($line["filter_type"] != 5) {
$filter = array();
if (sql_bool_to_bool($line["cat_filter"])) {
$feed_id = "CAT:" . (int)$line["cat_id"];
} else {
$feed_id = (int)$line["feed_id"];
}
$filter["enabled"] = $line["enabled"] ? "on" : "off";
$filter["rule"] = array(
json_encode(array(
"reg_exp" => $line["reg_exp"],
"feed_id" => $feed_id,
"filter_type" => $line["filter_type"])));
$filter["action"] = array(
json_encode(array(
"action_id" => $line["action_id"],
"action_param_label" => $line["action_param"],
"action_param" => $line["action_param"])));
// Oh god it's full of hacks
$_REQUEST = $filter;
$_SESSION["uid"] = $owner_uid;
$filters = new Pref_Filters($_REQUEST);
$filters->add();
}
}
}
if (isset($options["update-schema"])) {
_debug("checking for updates (" . DB_TYPE . ")...");
$updater = new DbUpdater(Db::get(), DB_TYPE, SCHEMA_VERSION);
if ($updater->isUpdateRequired()) {
_debug("schema update required, version " . $updater->getSchemaVersion() . " to " . SCHEMA_VERSION);
_debug("WARNING: please backup your database before continuing.");
_debug("Type 'yes' to continue.");
//if (read_stdin() != 'yes')
// exit;
for ($i = $updater->getSchemaVersion() + 1; $i <= SCHEMA_VERSION; $i++) {
_debug("performing update up to version $i...");
$result = $updater->performUpdateTo($i);
_debug($result ? "OK!" : "FAILED!");
if (!$result) return;
}
} else {
_debug("update not required.");
}
}
if (isset($options["list-plugins"])) {
$tmppluginhost = new PluginHost();
$tmppluginhost->load_all($tmppluginhost::KIND_ALL);
$enabled = array_map("trim", explode(",", PLUGINS));
echo "List of all available plugins:\n";
foreach ($tmppluginhost->get_plugins() as $name => $plugin) {
$about = $plugin->about();
$status = $about[3] ? "system" : "user";
if (in_array($name, $enabled)) $name .= "*";
printf("%-50s %-10s v%.2f (by %s)\n%s\n\n",
$name, $status, $about[0], $about[2], $about[1]);
}
echo "Plugins marked by * are currently enabled for all users.\n";
}
PluginHost::getInstance()->run_commands($options);
if (file_exists(LOCK_DIRECTORY . "/$lock_filename"))
unlink(LOCK_DIRECTORY . "/$lock_filename");
?>