mirror of
https://github.com/YunoHost-Apps/ttrss_ynh.git
synced 2024-10-01 13:34:46 +02:00
commit
00628be0a7
31 changed files with 1817 additions and 1675 deletions
21
conf/init.patch
Normal file
21
conf/init.patch
Normal file
|
@ -0,0 +1,21 @@
|
|||
*** init.php 2015-01-22 17:56:31.641845090 +0100
|
||||
--- init.php.1 2015-02-20 09:23:16.515269911 +0100
|
||||
***************
|
||||
*** 69,74 ****
|
||||
--- 69,84 ----
|
||||
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;
|
21
conf/update.patch
Normal file
21
conf/update.patch
Normal file
|
@ -0,0 +1,21 @@
|
|||
*** update.php 2015-02-20 09:41:40.231462387 +0100
|
||||
--- update.php.1 2015-02-20 09:42:07.911466665 +0100
|
||||
***************
|
||||
*** 311,318 ****
|
||||
_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...");
|
||||
--- 311,318 ----
|
||||
_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...");
|
|
@ -22,10 +22,14 @@ sudo yunohost app initdb $db_user -p $db_pwd -s $(readlink -e ../source/schema/T
|
|||
sudo yunohost app setting ttrss mysqlpwd -v $db_pwd
|
||||
|
||||
# Copy files to the right place
|
||||
final_path=/var/www/ttrss
|
||||
sudo mkdir -p $final_path
|
||||
sudo cp -r ../source/* $final_path
|
||||
sudo cp ../conf/config.php $final_path/
|
||||
final_path=/var/www/ttrss
|
||||
sudo mkdir -p $final_path
|
||||
sudo cp -r ../source/* $final_path
|
||||
sudo cp ../conf/config.php $final_path/
|
||||
sudo cp ../conf/*.patch /tmp/
|
||||
sudo patch -d $final_path -p0 < /tmp/update.patch
|
||||
sudo patch -d $final_path/plugins/auth_remote/ -p0 < /tmp/init.patch
|
||||
|
||||
|
||||
# Change variables in ttrss configuration
|
||||
sudo sed -i "s/yunouser/$db_user/g" $final_path/config.php
|
||||
|
@ -38,11 +42,23 @@ sudo chown root /etc/cron.d/ttrss
|
|||
sudo apt-get install php5-cli -y
|
||||
|
||||
#add folder
|
||||
sudo mkdir $final_path/cache/{export,images,upload,js}
|
||||
sudo mkdir $final_path/{feed-icons,lock}
|
||||
|
||||
sudo chmod -R 777 $final_path/cache/images && sudo chmod -R 777 $final_path/cache/upload && sudo chmod -R 777 $final_path/cache/export && sudo chmod -R 777 $final_path/cache/js && sudo chmod -R 777 $final_path/feed-icons && sudo chmod -R 777 $final_path/lock
|
||||
for i in export images upload js
|
||||
do
|
||||
if [ ! -d $final_path/cache/$i ];
|
||||
then
|
||||
sudo mkdir $final_path/cache/$i
|
||||
fi
|
||||
sudo chmod -R 777 $final_path/cache/$i
|
||||
done
|
||||
|
||||
for i in feed-icons lock
|
||||
do
|
||||
if [ ! -d $final_path/$i ];
|
||||
then
|
||||
sudo mkdir $final_path/$i
|
||||
fi
|
||||
sudo chmod -R 777 $final_path/$i
|
||||
done
|
||||
|
||||
# Set permissions to ttrss directory
|
||||
sudo chown -R www-data: $final_path
|
||||
|
|
|
@ -5,15 +5,15 @@ path=$(sudo yunohost app setting ttrss path)
|
|||
|
||||
db_user=ttrss
|
||||
db_pwd=$(sudo yunohost app setting ttrss mysqlpwd)
|
||||
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
|
||||
|
||||
final_path=/var/www/ttrss
|
||||
sudo mkdir -p $final_path
|
||||
|
||||
sudo cp -a ../source/* $final_path
|
||||
sudo cp ../conf/config.php $final_path/
|
||||
sudo cp ../conf/*.patch /tmp/
|
||||
sudo patch -d $final_path -p0 < /tmp/update.patch
|
||||
sudo patch -d $final_path/plugins/auth_remote/ -p0 < /tmp/init.patch
|
||||
|
||||
# Change variables in ttrss configuration
|
||||
sudo sed -i "s/yunouser/$db_user/g" $final_path/config.php
|
||||
|
@ -28,7 +28,9 @@ sudo sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf
|
|||
sudo sed -i "s@ALIASTOCHANGE@$final_path/@g" ../conf/nginx.conf
|
||||
sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/ttrss.conf
|
||||
|
||||
sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/ttrss.conf
|
||||
sudo service nginx reload
|
||||
sudo yunohost app ssowatconf
|
||||
sudo yunohost app setting ttrss skipped_uris -v "/public.php,/api"
|
||||
|
||||
# Update database schema
|
||||
sudo su - www-data -c "$final_path/update.php --update-schema"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
class API extends Handler {
|
||||
|
||||
const API_LEVEL = 9;
|
||||
const API_LEVEL = 11;
|
||||
|
||||
const STATUS_OK = 0;
|
||||
const STATUS_ERR = 1;
|
||||
|
@ -201,6 +201,10 @@ class API extends Handler {
|
|||
$sanitize_content = !isset($_REQUEST["sanitize"]) ||
|
||||
sql_bool_to_bool($_REQUEST["sanitize"]);
|
||||
$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;
|
||||
switch ($_REQUEST["order_by"]) {
|
||||
|
@ -223,7 +227,7 @@ class API extends Handler {
|
|||
$headlines = $this->api_get_headlines($feed_id, $limit, $offset,
|
||||
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order,
|
||||
$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);
|
||||
} else {
|
||||
|
@ -633,7 +637,7 @@ class API extends Handler {
|
|||
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order,
|
||||
$include_attachments, $since_id,
|
||||
$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)) {
|
||||
// Update the feed if required with some basic flood control
|
||||
|
@ -666,16 +670,31 @@ class API extends Handler {
|
|||
$headlines = array();
|
||||
|
||||
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) {
|
||||
$line = $p->hook_query_headlines($line, 100, true);
|
||||
$line = $p->hook_query_headlines($line, $excerpt_length, true);
|
||||
}
|
||||
|
||||
$is_updated = ($line["last_read"] == "" &&
|
||||
($line["unread"] != "t" && $line["unread"] != "1"));
|
||||
|
||||
$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 (!$labels) $labels = get_article_labels($line["id"]);
|
||||
|
|
|
@ -491,7 +491,9 @@ class Opml extends Handler_Protected {
|
|||
|
||||
if (is_file($tmp_file)) {
|
||||
$doc = new DOMDocument();
|
||||
libxml_disable_entity_loader(false);
|
||||
$doc->load($tmp_file);
|
||||
libxml_disable_entity_loader(true);
|
||||
unlink($tmp_file);
|
||||
} else if (!$doc) {
|
||||
print_error(__('Error: unable to find moved OPML file.'));
|
||||
|
|
|
@ -571,7 +571,8 @@ class Pref_Prefs extends Handler_Protected {
|
|||
|
||||
} 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,
|
||||
'dojoType="dijit.form.Select"');
|
||||
|
|
|
@ -93,6 +93,10 @@
|
|||
background : white;
|
||||
}
|
||||
|
||||
.claro #feedTree.dijitTree .dijitTreeRowSelected {
|
||||
box-shadow : -1px 0px 2px -1px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.claro .dijitTree .dijitTreeRowHover {
|
||||
background : #f0f0f0;
|
||||
border-color : #ddd;
|
||||
|
|
|
@ -7,6 +7,11 @@ body#ttrssMain, body#ttrssPrefs, body#ttrssLogin, body {
|
|||
font-size: 14px;
|
||||
}
|
||||
|
||||
body#ttrssMain {
|
||||
overflow : hidden;
|
||||
max-height : 100%;
|
||||
}
|
||||
|
||||
div.postReply {
|
||||
padding : 0px;
|
||||
}
|
||||
|
@ -138,18 +143,30 @@ a:hover {
|
|||
position : absolute;
|
||||
}
|
||||
|
||||
#notify.visible {
|
||||
transform: translate(0, -35px);
|
||||
-webkit-transform: translate(0, -35px);
|
||||
-o-transform: translate(0, -35px);
|
||||
-moz-transform: translate(0, -35px);
|
||||
}
|
||||
|
||||
#notify {
|
||||
bottom : 10px;
|
||||
right : 20px;
|
||||
border-width : 1px;
|
||||
bottom : -35px;
|
||||
right : 0px;
|
||||
height : 20px;
|
||||
left : 0px;
|
||||
border-width : 1px 0px 0px 0px;
|
||||
border-style : solid;
|
||||
position : absolute;
|
||||
position : fixed;
|
||||
font-size : 12px;
|
||||
z-index : 99;
|
||||
max-width : 200px;
|
||||
min-width : 100px;
|
||||
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 {
|
||||
|
@ -176,17 +193,17 @@ a:hover {
|
|||
background-color : #fff7d5;
|
||||
}
|
||||
|
||||
.notify.progress {
|
||||
.notify.notify_progress {
|
||||
border-color : #d7c47a;
|
||||
background-color : #fff7d5;
|
||||
}
|
||||
|
||||
.notify.info {
|
||||
.notify.notify_info {
|
||||
border-color : #88b0f0;
|
||||
background-color : #ecf4ff;
|
||||
}
|
||||
|
||||
.notify.error {
|
||||
.notify.notify_error {
|
||||
background-color : #ffcccc;
|
||||
border-color : #ff0000;
|
||||
}
|
||||
|
@ -796,7 +813,7 @@ div.fatalError textarea {
|
|||
|
||||
#feeds-holder {
|
||||
padding : 0px;
|
||||
border-width : 0px 1px 0px 0px;
|
||||
border-width : 0px 0px 0px 0px;
|
||||
border-style : solid;
|
||||
border-color : #ddd;
|
||||
overflow : hidden;
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
$fetch_curl_used = false;
|
||||
$suppress_debugging = false;
|
||||
|
||||
libxml_disable_entity_loader(true);
|
||||
|
||||
mb_internal_encoding("UTF-8");
|
||||
date_default_timezone_set('UTC');
|
||||
if (defined('E_DEPRECATED')) {
|
||||
|
@ -357,6 +359,9 @@
|
|||
$url = ltrim($url, ' ');
|
||||
$url = str_replace(' ', '%20', $url);
|
||||
|
||||
if (strpos($url, "//") === 0)
|
||||
$url = 'http:' . $url;
|
||||
|
||||
if (!defined('NO_CURL') && function_exists('curl_init')) {
|
||||
|
||||
$fetch_curl_used = true;
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
$params["default_view_order_by"] = get_pref("_DEFAULT_VIEW_ORDER_BY");
|
||||
$params["bw_limit"] = (int) $_SESSION["bw_limit"];
|
||||
$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["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) {
|
||||
if (!$owner) $owner = $_SESSION["uid"];
|
||||
|
||||
|
@ -894,8 +912,15 @@
|
|||
|
||||
$entries = $xpath->query('//iframe');
|
||||
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',
|
||||
|
@ -1958,8 +1983,8 @@
|
|||
}
|
||||
|
||||
function getLastArticleId() {
|
||||
$result = db_query("SELECT MAX(ref_id) AS id FROM ttrss_user_entries
|
||||
WHERE owner_uid = " . $_SESSION["uid"]);
|
||||
$result = db_query("SELECT ref_id AS id FROM ttrss_user_entries
|
||||
WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY ref_id DESC LIMIT 1");
|
||||
|
||||
if (db_num_rows($result) == 1) {
|
||||
return db_fetch_result($result, 0, "id");
|
||||
|
@ -2400,4 +2425,21 @@
|
|||
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;
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -481,7 +481,7 @@
|
|||
|
||||
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) {
|
||||
_debug("registering title: $feed_title", $debug_enabled);
|
||||
|
@ -707,7 +707,11 @@
|
|||
db_query("UPDATE ttrss_entries SET date_updated = NOW()
|
||||
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);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
define('VERSION_STATIC', '1.14');
|
||||
define('VERSION_STATIC', '1.15.3');
|
||||
|
||||
function get_version() {
|
||||
date_default_timezone_set('UTC');
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<?php if ($_SESSION["uid"]) {
|
||||
$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");
|
||||
} else {
|
||||
echo stylesheet_tag("themes/default.css");
|
||||
|
@ -138,7 +138,7 @@
|
|||
</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="headlines-tmp" style="display : none"></div>
|
||||
|
||||
|
|
|
@ -182,11 +182,6 @@ function param_unescape(arg) {
|
|||
return unescape(arg);
|
||||
}
|
||||
|
||||
|
||||
function hide_notify() {
|
||||
Element.hide('notify');
|
||||
}
|
||||
|
||||
function notify_real(msg, no_hide, n_type) {
|
||||
|
||||
var n = $("notify");
|
||||
|
@ -198,13 +193,11 @@ function notify_real(msg, no_hide, n_type) {
|
|||
}
|
||||
|
||||
if (msg == "") {
|
||||
if (Element.visible(n)) {
|
||||
notify_hide_timerid = window.setTimeout("hide_notify()", 0);
|
||||
if (n.hasClassName("visible")) {
|
||||
notify_hide_timerid = window.setTimeout(function() {
|
||||
n.removeClassName("visible") }, 0);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
Element.show(n);
|
||||
new Effect.Highlight(n);
|
||||
}
|
||||
|
||||
/* types:
|
||||
|
@ -218,30 +211,40 @@ function notify_real(msg, no_hide, n_type) {
|
|||
|
||||
msg = "<span class=\"msg\"> " + __(msg) + "</span>";
|
||||
|
||||
if (n_type == 1) {
|
||||
n.className = "notify";
|
||||
} else if (n_type == 2) {
|
||||
n.className = "notify progress";
|
||||
if (n_type == 2) {
|
||||
msg = "<span><img src='images/indicator_white.gif'></span>" + msg;
|
||||
no_hide = true;
|
||||
} else if (n_type == 3) {
|
||||
n.className = "notify error";
|
||||
msg = "<span><img src='images/alert.png'></span>" + msg;
|
||||
} else if (n_type == 4) {
|
||||
n.className = "notify info";
|
||||
msg = "<span><img src='images/information.png'></span>" + msg;
|
||||
}
|
||||
|
||||
msg += " <span><img src=\"images/cross.png\" class=\"close\" title=\"" +
|
||||
__("Click to close") + "\" onclick=\"notify('')\"></span>";
|
||||
|
||||
// msg = "<img src='images/live_com_loading.gif'> " + msg;
|
||||
|
||||
n.innerHTML = msg;
|
||||
|
||||
if (!no_hide) {
|
||||
notify_hide_timerid = window.setTimeout("hide_notify()", 5*1000);
|
||||
}
|
||||
window.setTimeout(function() {
|
||||
// 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) {
|
||||
|
|
|
@ -302,21 +302,27 @@ function init() {
|
|||
hotkey_actions["collapse_article"] = function() {
|
||||
var id = getActiveArticleId();
|
||||
var elem = $("CICD-"+id);
|
||||
if(elem.visible()) {
|
||||
cdmCollapseArticle(null, id);
|
||||
}
|
||||
else {
|
||||
cdmExpandArticle(id);
|
||||
|
||||
if (elem) {
|
||||
if (elem.visible()) {
|
||||
cdmCollapseArticle(null, id);
|
||||
}
|
||||
else {
|
||||
cdmExpandArticle(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
hotkey_actions["toggle_expand"] = function() {
|
||||
var id = getActiveArticleId();
|
||||
var elem = $("CICD-"+id);
|
||||
if(elem.visible()) {
|
||||
cdmCollapseArticle(null, id, false);
|
||||
}
|
||||
else {
|
||||
cdmExpandArticle(id);
|
||||
|
||||
if (elem) {
|
||||
if (elem.visible()) {
|
||||
cdmCollapseArticle(null, id, false);
|
||||
}
|
||||
else {
|
||||
cdmExpandArticle(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
hotkey_actions["search_dialog"] = function() {
|
||||
|
|
Binary file not shown.
|
@ -12,8 +12,8 @@ msgstr ""
|
|||
"Project-Id-Version: Tiny Tiny RSS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-09-06 15:10+0400\n"
|
||||
"PO-Revision-Date: 2014-09-06 20:33+0100\n"
|
||||
"Last-Translator: Heiko Adams <heiko.adams@gmai.com>\n"
|
||||
"PO-Revision-Date: 2014-11-19 18:13+0100\n"
|
||||
"Last-Translator: Robert Wetzlmayr <r.wetzlmayr@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -21,7 +21,7 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 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
|
||||
msgid "Use default"
|
||||
|
@ -1771,7 +1771,7 @@ msgstr "Maximales Alter neuer Artikel (in Stunden)"
|
|||
|
||||
#: classes/pref/prefs.php:41
|
||||
msgid "Hide feeds with no unread articles"
|
||||
msgstr "Feeds ohne unglesene Nachrichten verbergen"
|
||||
msgstr "Feeds ohne ungelesene Nachrichten verbergen"
|
||||
|
||||
#: classes/pref/prefs.php:42
|
||||
msgid "Show special feeds when hiding read feeds"
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -6,23 +6,33 @@ class Af_Comics_Dilbert extends Af_ComicFilter {
|
|||
}
|
||||
|
||||
function process(&$article) {
|
||||
$owner_uid = $article["owner_uid"];
|
||||
|
||||
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->loadHTML(fetch_file_contents($article["link"]));
|
||||
@$doc->loadHTML($res);
|
||||
|
||||
$basenode = false;
|
||||
|
||||
if ($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();
|
||||
|
||||
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",
|
||||
rewrite_relative_url("http://dilbert.com/",
|
||||
|
@ -31,7 +41,7 @@ class Af_Comics_Dilbert extends Af_ComicFilter {
|
|||
$basenode = $entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
if ($basenode) {
|
||||
$article["content"] = $doc->saveXML($basenode);
|
||||
|
|
|
@ -56,7 +56,9 @@ class Af_Comics_Pa extends Af_ComicFilter {
|
|||
if ($header->parentNode) { $header->parentNode->removeChild($header); }
|
||||
|
||||
$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"])');
|
||||
foreach ($uninteresting as $i) {
|
||||
|
|
32
source/plugins/af_comics/filters/af_comics_tfd.php
Normal file
32
source/plugins/af_comics/filters/af_comics_tfd.php
Normal 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;
|
||||
}
|
||||
}
|
||||
?>
|
79
source/plugins/af_tumblr_1280/init.php
Normal file
79
source/plugins/af_tumblr_1280/init.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
88
source/plugins/af_zz_imgsetsizes/init.php
Normal file
88
source/plugins/af_zz_imgsetsizes/init.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -69,16 +69,6 @@ class Auth_Remote extends Plugin implements IAuthModule {
|
|||
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;
|
||||
|
|
|
@ -4,7 +4,7 @@ class No_Iframes extends Plugin {
|
|||
|
||||
function about() {
|
||||
return array(1.0,
|
||||
"Remove embedded iframes",
|
||||
"Remove embedded iframes (unless whitelisted)",
|
||||
"fox");
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,13 @@ class No_Iframes extends Plugin {
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<?php if ($_SESSION["uid"]) {
|
||||
$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");
|
||||
} else {
|
||||
echo stylesheet_tag("themes/default.css");
|
||||
|
@ -94,7 +94,7 @@
|
|||
|
||||
<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="overlay">
|
||||
|
|
|
@ -3,12 +3,17 @@
|
|||
body#ttrssMain #feeds-holder {
|
||||
background : #222;
|
||||
border-color : #666;
|
||||
border-left-width : 1px;
|
||||
}
|
||||
|
||||
body#ttrssMain #headlines-frame {
|
||||
border-color : #ddd;
|
||||
}
|
||||
|
||||
body#ttrssMain div.whiteBox {
|
||||
border-color : #666;
|
||||
}
|
||||
|
||||
body#ttrssMain #content-insert {
|
||||
background : #333;
|
||||
}
|
||||
|
@ -132,6 +137,7 @@ body#ttrssMain #feedTree img,
|
|||
body#ttrssMain .postContent img {
|
||||
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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue