foreach ($plugins as $class) {
$class = trim($class);
$class_file = strtolower(basename($class));
- $file = dirname(__FILE__)."/../plugins/$class_file/$class_file.php";
+ $file = dirname(__FILE__)."/../plugins/$class_file/init.php";
if (!isset($this->plugins[$class])) {
if (file_exists($file)) require_once $file;
+++ /dev/null
-<?php
-class Af_Explosm extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Strip unnecessary stuff from Cyanide and Happiness feeds",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
- }
-
- function hook_article_filter($article) {
- $owner_uid = $article["owner_uid"];
-
- if (strpos($article["link"], "explosm.net/comics") !== FALSE &&
- strpos($article["guid"], "explosm,$owner_uid:") === FALSE) {
-
- $doc = new DOMDocument();
- @$doc->loadHTML(fetch_file_contents($article["link"]));
-
- $basenode = false;
-
- if ($doc) {
- $xpath = new DOMXPath($doc);
- $entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
-
- $matches = array();
-
- foreach ($entries as $entry) {
-
- if (preg_match("/(http:\/\/.*\/db\/files\/Comics\/.*)/i", $entry->getAttribute("src"), $matches)) {
-
- $basenode = $entry;
- break;
- }
- }
-
- if ($basenode) {
- $article["content"] = $doc->saveXML($basenode, LIBXML_NOEMPTYTAG);
-
- // we need to update guid with owner_uid because our local article is different from the one
- // other users with this plugin disabled might get
- $article["guid"] = "explosm,$owner_uid:" . $article["guid"];
- }
- }
- }
-
- return $article;
- }
-}
-?>
--- /dev/null
+<?php
+class Af_Explosm extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Strip unnecessary stuff from Cyanide and Happiness feeds",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
+ }
+
+ function hook_article_filter($article) {
+ $owner_uid = $article["owner_uid"];
+
+ if (strpos($article["link"], "explosm.net/comics") !== FALSE &&
+ strpos($article["guid"], "explosm,$owner_uid:") === FALSE) {
+
+ $doc = new DOMDocument();
+ @$doc->loadHTML(fetch_file_contents($article["link"]));
+
+ $basenode = false;
+
+ if ($doc) {
+ $xpath = new DOMXPath($doc);
+ $entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
+
+ $matches = array();
+
+ foreach ($entries as $entry) {
+
+ if (preg_match("/(http:\/\/.*\/db\/files\/Comics\/.*)/i", $entry->getAttribute("src"), $matches)) {
+
+ $basenode = $entry;
+ break;
+ }
+ }
+
+ if ($basenode) {
+ $article["content"] = $doc->saveXML($basenode, LIBXML_NOEMPTYTAG);
+
+ // we need to update guid with owner_uid because our local article is different from the one
+ // other users with this plugin disabled might get
+ $article["guid"] = "explosm,$owner_uid:" . $article["guid"];
+ }
+ }
+ }
+
+ return $article;
+ }
+}
+?>
+++ /dev/null
-<?php
-class Af_GoComics extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Strip unnecessary stuff from gocomics feeds",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
- }
-
- function hook_article_filter($article) {
- $owner_uid = $article["owner_uid"];
-
- if (strpos($article["guid"], "gocomics.com") !== FALSE && strpos($article["guid"], "gocomics,$owner_uid:") === FALSE) {
- $doc = new DOMDocument();
- @$doc->loadHTML(fetch_file_contents($article["link"]));
-
- $basenode = false;
-
- if ($doc) {
- $xpath = new DOMXPath($doc);
- $entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
-
- $matches = array();
-
- foreach ($entries as $entry) {
-
- if (preg_match("/(http:\/\/assets.amuniversal.com\/.*)/i", $entry->getAttribute("src"), $matches)) {
-
- $entry->setAttribute("src", $matches[0]);
- $basenode = $entry;
- break;
- }
- }
-
- if ($basenode) {
- $article["content"] = $doc->saveXML($basenode, LIBXML_NOEMPTYTAG);
-
- // we need to update guid with owner_uid because our local article is different from the one
- // other users with this plugin disabled might get
- $article["guid"] = "gocomics,$owner_uid:" . $article["guid"];
- }
- }
- }
-
- return $article;
- }
-}
-?>
--- /dev/null
+<?php
+class Af_GoComics extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Strip unnecessary stuff from gocomics feeds",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
+ }
+
+ function hook_article_filter($article) {
+ $owner_uid = $article["owner_uid"];
+
+ if (strpos($article["guid"], "gocomics.com") !== FALSE && strpos($article["guid"], "gocomics,$owner_uid:") === FALSE) {
+ $doc = new DOMDocument();
+ @$doc->loadHTML(fetch_file_contents($article["link"]));
+
+ $basenode = false;
+
+ if ($doc) {
+ $xpath = new DOMXPath($doc);
+ $entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
+
+ $matches = array();
+
+ foreach ($entries as $entry) {
+
+ if (preg_match("/(http:\/\/assets.amuniversal.com\/.*)/i", $entry->getAttribute("src"), $matches)) {
+
+ $entry->setAttribute("src", $matches[0]);
+ $basenode = $entry;
+ break;
+ }
+ }
+
+ if ($basenode) {
+ $article["content"] = $doc->saveXML($basenode, LIBXML_NOEMPTYTAG);
+
+ // we need to update guid with owner_uid because our local article is different from the one
+ // other users with this plugin disabled might get
+ $article["guid"] = "gocomics,$owner_uid:" . $article["guid"];
+ }
+ }
+ }
+
+ return $article;
+ }
+}
+?>
+++ /dev/null
-<?php
-class Af_PennyArcade extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Strip unnecessary stuff from PA feeds",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
- }
-
- function hook_article_filter($article) {
- $owner_uid = $article["owner_uid"];
-
- if (strpos($article["link"], "penny-arcade.com") !== FALSE && strpos($article["title"], "Comic:") !== FALSE &&
- strpos($article["guid"], "pennyarcade,$owner_uid:") === FALSE) {
-
- $doc = new DOMDocument();
- @$doc->loadHTML(fetch_file_contents($article["link"]));
-
- $basenode = false;
-
- if ($doc) {
- $xpath = new DOMXPath($doc);
- $entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
-
- $matches = array();
-
- foreach ($entries as $entry) {
-
- if (preg_match("/(http:\/\/art.penny-arcade.com\/.*)/i", $entry->getAttribute("src"), $matches)) {
-
- $basenode = $entry;
- break;
- }
- }
-
- if ($basenode) {
- $article["content"] = $doc->saveXML($basenode, LIBXML_NOEMPTYTAG);
-
- // we need to update guid with owner_uid because our local article is different from the one
- // other users with this plugin disabled might get
- $article["guid"] = "pennyarcade,$owner_uid:" . $article["guid"];
- }
- }
- }
-
- return $article;
- }
-}
-?>
--- /dev/null
+<?php
+class Af_PennyArcade extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Strip unnecessary stuff from PA feeds",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
+ }
+
+ function hook_article_filter($article) {
+ $owner_uid = $article["owner_uid"];
+
+ if (strpos($article["link"], "penny-arcade.com") !== FALSE && strpos($article["title"], "Comic:") !== FALSE &&
+ strpos($article["guid"], "pennyarcade,$owner_uid:") === FALSE) {
+
+ $doc = new DOMDocument();
+ @$doc->loadHTML(fetch_file_contents($article["link"]));
+
+ $basenode = false;
+
+ if ($doc) {
+ $xpath = new DOMXPath($doc);
+ $entries = $xpath->query('(//img[@src])'); // we might also check for img[@class='strip'] I guess...
+
+ $matches = array();
+
+ foreach ($entries as $entry) {
+
+ if (preg_match("/(http:\/\/art.penny-arcade.com\/.*)/i", $entry->getAttribute("src"), $matches)) {
+
+ $basenode = $entry;
+ break;
+ }
+ }
+
+ if ($basenode) {
+ $article["content"] = $doc->saveXML($basenode, LIBXML_NOEMPTYTAG);
+
+ // we need to update guid with owner_uid because our local article is different from the one
+ // other users with this plugin disabled might get
+ $article["guid"] = "pennyarcade,$owner_uid:" . $article["guid"];
+ }
+ }
+ }
+
+ return $article;
+ }
+}
+?>
+++ /dev/null
-<?php
-class Af_RedditImgur extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Inline image links in Reddit RSS feeds",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
- }
-
- function hook_article_filter($article) {
-
- if (strpos($article["link"], "reddit.com/r/") !== FALSE) {
- $doc = new DOMDocument();
- @$doc->loadHTML($article["content"]);
-
- if ($doc) {
- $xpath = new DOMXPath($doc);
- $entries = $xpath->query('(//a[@href]|//img[@src])');
-
- foreach ($entries as $entry) {
- if ($entry->hasAttribute("href")) {
- if (preg_match("/\.(jpg|jpeg|gif|png)$/i", $entry->getAttribute("href"))) {
-
- $img = $doc->createElement('img');
- $img->setAttribute("src", $entry->getAttribute("href"));
-
- $entry->parentNode->replaceChild($img, $entry);
- }
- }
-
- // remove tiny thumbnails
- if ($entry->hasAttribute("src")) {
- if ($entry->parentNode && $entry->parentNode->parentNode) {
- $entry->parentNode->parentNode->removeChild($entry->parentNode);
- }
- }
- }
-
- $node = $doc->getElementsByTagName('body')->item(0);
-
- if ($node) {
- $article["content"] = $doc->saveXML($node, LIBXML_NOEMPTYTAG);
- }
- }
- }
-
- return $article;
- }
-}
-?>
--- /dev/null
+<?php
+class Af_RedditImgur extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Inline image links in Reddit RSS feeds",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_FILTER, $this);
+ }
+
+ function hook_article_filter($article) {
+
+ if (strpos($article["link"], "reddit.com/r/") !== FALSE) {
+ $doc = new DOMDocument();
+ @$doc->loadHTML($article["content"]);
+
+ if ($doc) {
+ $xpath = new DOMXPath($doc);
+ $entries = $xpath->query('(//a[@href]|//img[@src])');
+
+ foreach ($entries as $entry) {
+ if ($entry->hasAttribute("href")) {
+ if (preg_match("/\.(jpg|jpeg|gif|png)$/i", $entry->getAttribute("href"))) {
+
+ $img = $doc->createElement('img');
+ $img->setAttribute("src", $entry->getAttribute("href"));
+
+ $entry->parentNode->replaceChild($img, $entry);
+ }
+ }
+
+ // remove tiny thumbnails
+ if ($entry->hasAttribute("src")) {
+ if ($entry->parentNode && $entry->parentNode->parentNode) {
+ $entry->parentNode->parentNode->removeChild($entry->parentNode);
+ }
+ }
+ }
+
+ $node = $doc->getElementsByTagName('body')->item(0);
+
+ if ($node) {
+ $article["content"] = $doc->saveXML($node, LIBXML_NOEMPTYTAG);
+ }
+ }
+ }
+
+ return $article;
+ }
+}
+?>
+++ /dev/null
-<?php
-/* Requires php-imap
- Put the following options in config.php:
-
- define('IMAP_AUTH_SERVER', 'your.imap.server:port');
- define('IMAP_AUTH_OPTIONS', '/tls/novalidate-cert/norsh');
- // More about options: http://php.net/manual/ru/function.imap-open.php
-
-*/
-class Auth_Imap extends Plugin implements IAuthModule {
-
- private $link;
- private $host;
- private $base;
-
- function about() {
- return array(1.0,
- "Authenticates against an IMAP server (configured in config.php)",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
- $this->base = new Auth_Base($this->link);
-
- $host->add_hook($host::HOOK_AUTH_USER, $this);
- }
-
- function authenticate($login, $password) {
-
- if ($login && $password) {
- $imap = imap_open(
- "{".IMAP_AUTH_SERVER.IMAP_AUTH_OPTIONS."}INBOX",
- $login,
- $password);
-
- if ($imap) {
- imap_close($imap);
-
- return $this->base->auto_create_user($login);
- }
- }
-
- return false;
- }
-
-}
-
-?>
--- /dev/null
+<?php
+/* Requires php-imap
+ Put the following options in config.php:
+
+ define('IMAP_AUTH_SERVER', 'your.imap.server:port');
+ define('IMAP_AUTH_OPTIONS', '/tls/novalidate-cert/norsh');
+ // More about options: http://php.net/manual/ru/function.imap-open.php
+
+*/
+class Auth_Imap extends Plugin implements IAuthModule {
+
+ private $link;
+ private $host;
+ private $base;
+
+ function about() {
+ return array(1.0,
+ "Authenticates against an IMAP server (configured in config.php)",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+ $this->base = new Auth_Base($this->link);
+
+ $host->add_hook($host::HOOK_AUTH_USER, $this);
+ }
+
+ function authenticate($login, $password) {
+
+ if ($login && $password) {
+ $imap = imap_open(
+ "{".IMAP_AUTH_SERVER.IMAP_AUTH_OPTIONS."}INBOX",
+ $login,
+ $password);
+
+ if ($imap) {
+ imap_close($imap);
+
+ return $this->base->auto_create_user($login);
+ }
+ }
+
+ return false;
+ }
+
+}
+
+?>
+++ /dev/null
-<?php
-class Auth_Internal extends Plugin implements IAuthModule {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Authenticates against internal tt-rss database",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_AUTH_USER, $this);
- }
-
- function authenticate($login, $password) {
-
- $pwd_hash1 = encrypt_password($password);
- $pwd_hash2 = encrypt_password($password, $login);
- $login = db_escape_string($login);
- $otp = db_escape_string($_REQUEST["otp"]);
-
- if (get_schema_version($this->link) > 96) {
- if (!defined('AUTH_DISABLE_OTP') || !AUTH_DISABLE_OTP) {
- $result = db_query($this->link, "SELECT otp_enabled,salt FROM ttrss_users WHERE
- login = '$login'");
-
- if (db_num_rows($result) > 0) {
- require_once "lib/otphp/vendor/base32.php";
- require_once "lib/otphp/lib/otp.php";
- require_once "lib/otphp/lib/totp.php";
-
- $base32 = new Base32();
-
- $otp_enabled = sql_bool_to_bool(db_fetch_result($result, 0, "otp_enabled"));
- $secret = $base32->encode(sha1(db_fetch_result($result, 0, "salt")));
-
- $topt = new \OTPHP\TOTP($secret);
- $otp_check = $topt->now();
-
- if ($otp_enabled) {
- if ($otp) {
- if ($otp != $otp_check) {
- return false;
- }
- } else {
- $return = urlencode($_REQUEST["return"]);
- ?><html>
- <head><title>Tiny Tiny RSS</title></head>
- <body>
- <form action="public.php?return=<?php echo $return ?>"
- method="POST">
- <input type="hidden" name="op" value="login">
- <input type="hidden" name="login" value="<?php echo htmlspecialchars($login) ?>">
- <input type="hidden" name="password" value="<?php echo htmlspecialchars($password) ?>">
-
- <label><?php echo __("Please enter your one time password:") ?></label>
- <input type="password" size="6" name="otp"/>
- <input type="submit" value="Continue"/>
- </form>
- <script type="text/javascript">
- document.forms[0].otp.focus();
- </script>
- <?php
- exit;
- }
- }
- }
- }
- }
-
- if (get_schema_version($this->link) > 87) {
-
- $result = db_query($this->link, "SELECT salt FROM ttrss_users WHERE
- login = '$login'");
-
- if (db_num_rows($result) != 1) {
- return false;
- }
-
- $salt = db_fetch_result($result, 0, "salt");
-
- if ($salt == "") {
-
- $query = "SELECT id
- FROM ttrss_users WHERE
- login = '$login' AND (pwd_hash = '$pwd_hash1' OR
- pwd_hash = '$pwd_hash2')";
-
- // verify and upgrade password to new salt base
-
- $result = db_query($this->link, $query);
-
- if (db_num_rows($result) == 1) {
- // upgrade password to MODE2
-
- $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
- $pwd_hash = encrypt_password($password, $salt, true);
-
- db_query($this->link, "UPDATE ttrss_users SET
- pwd_hash = '$pwd_hash', salt = '$salt' WHERE login = '$login'");
-
- $query = "SELECT id
- FROM ttrss_users WHERE
- login = '$login' AND pwd_hash = '$pwd_hash'";
-
- } else {
- return false;
- }
-
- } else {
-
- $pwd_hash = encrypt_password($password, $salt, true);
-
- $query = "SELECT id
- FROM ttrss_users WHERE
- login = '$login' AND pwd_hash = '$pwd_hash'";
-
- }
-
- } else {
- $query = "SELECT id
- FROM ttrss_users WHERE
- login = '$login' AND (pwd_hash = '$pwd_hash1' OR
- pwd_hash = '$pwd_hash2')";
- }
-
- $result = db_query($this->link, $query);
-
- if (db_num_rows($result) == 1) {
- return db_fetch_result($result, 0, "id");
- }
-
- return false;
- }
-
- function check_password($owner_uid, $password) {
- $owner_uid = db_escape_string($owner_uid);
-
- $result = db_query($this->link, "SELECT salt,login FROM ttrss_users WHERE
- id = '$owner_uid'");
-
- $salt = db_fetch_result($result, 0, "salt");
- $login = db_fetch_result($result, 0, "login");
-
- if (!$salt) {
- $password_hash1 = encrypt_password($password);
- $password_hash2 = encrypt_password($password, $login);
-
- $query = "SELECT id FROM ttrss_users WHERE
- id = '$owner_uid' AND (pwd_hash = '$password_hash1' OR
- pwd_hash = '$password_hash2')";
-
- } else {
- $password_hash = encrypt_password($password, $salt, true);
-
- $query = "SELECT id FROM ttrss_users WHERE
- id = '$owner_uid' AND pwd_hash = '$password_hash'";
- }
-
- $result = db_query($this->link, $query);
-
- return db_num_rows($result) != 0;
- }
-
- function change_password($owner_uid, $old_password, $new_password) {
- $owner_uid = db_escape_string($owner_uid);
-
- if ($this->check_password($owner_uid, $old_password)) {
-
- $new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
- $new_password_hash = encrypt_password($new_password, $new_salt, true);
-
- db_query($this->link, "UPDATE ttrss_users SET
- pwd_hash = '$new_password_hash', salt = '$new_salt', otp_enabled = false
- WHERE id = '$owner_uid'");
-
- $_SESSION["pwd_hash"] = $new_password_hash;
-
- return __("Password has been changed.");
- } else {
- return "ERROR: ".__('Old password is incorrect.');
- }
- }
-}
-?>
--- /dev/null
+<?php
+class Auth_Internal extends Plugin implements IAuthModule {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Authenticates against internal tt-rss database",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_AUTH_USER, $this);
+ }
+
+ function authenticate($login, $password) {
+
+ $pwd_hash1 = encrypt_password($password);
+ $pwd_hash2 = encrypt_password($password, $login);
+ $login = db_escape_string($login);
+ $otp = db_escape_string($_REQUEST["otp"]);
+
+ if (get_schema_version($this->link) > 96) {
+ if (!defined('AUTH_DISABLE_OTP') || !AUTH_DISABLE_OTP) {
+ $result = db_query($this->link, "SELECT otp_enabled,salt FROM ttrss_users WHERE
+ login = '$login'");
+
+ if (db_num_rows($result) > 0) {
+ require_once "lib/otphp/vendor/base32.php";
+ require_once "lib/otphp/lib/otp.php";
+ require_once "lib/otphp/lib/totp.php";
+
+ $base32 = new Base32();
+
+ $otp_enabled = sql_bool_to_bool(db_fetch_result($result, 0, "otp_enabled"));
+ $secret = $base32->encode(sha1(db_fetch_result($result, 0, "salt")));
+
+ $topt = new \OTPHP\TOTP($secret);
+ $otp_check = $topt->now();
+
+ if ($otp_enabled) {
+ if ($otp) {
+ if ($otp != $otp_check) {
+ return false;
+ }
+ } else {
+ $return = urlencode($_REQUEST["return"]);
+ ?><html>
+ <head><title>Tiny Tiny RSS</title></head>
+ <body>
+ <form action="public.php?return=<?php echo $return ?>"
+ method="POST">
+ <input type="hidden" name="op" value="login">
+ <input type="hidden" name="login" value="<?php echo htmlspecialchars($login) ?>">
+ <input type="hidden" name="password" value="<?php echo htmlspecialchars($password) ?>">
+
+ <label><?php echo __("Please enter your one time password:") ?></label>
+ <input type="password" size="6" name="otp"/>
+ <input type="submit" value="Continue"/>
+ </form>
+ <script type="text/javascript">
+ document.forms[0].otp.focus();
+ </script>
+ <?php
+ exit;
+ }
+ }
+ }
+ }
+ }
+
+ if (get_schema_version($this->link) > 87) {
+
+ $result = db_query($this->link, "SELECT salt FROM ttrss_users WHERE
+ login = '$login'");
+
+ if (db_num_rows($result) != 1) {
+ return false;
+ }
+
+ $salt = db_fetch_result($result, 0, "salt");
+
+ if ($salt == "") {
+
+ $query = "SELECT id
+ FROM ttrss_users WHERE
+ login = '$login' AND (pwd_hash = '$pwd_hash1' OR
+ pwd_hash = '$pwd_hash2')";
+
+ // verify and upgrade password to new salt base
+
+ $result = db_query($this->link, $query);
+
+ if (db_num_rows($result) == 1) {
+ // upgrade password to MODE2
+
+ $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
+ $pwd_hash = encrypt_password($password, $salt, true);
+
+ db_query($this->link, "UPDATE ttrss_users SET
+ pwd_hash = '$pwd_hash', salt = '$salt' WHERE login = '$login'");
+
+ $query = "SELECT id
+ FROM ttrss_users WHERE
+ login = '$login' AND pwd_hash = '$pwd_hash'";
+
+ } else {
+ return false;
+ }
+
+ } else {
+
+ $pwd_hash = encrypt_password($password, $salt, true);
+
+ $query = "SELECT id
+ FROM ttrss_users WHERE
+ login = '$login' AND pwd_hash = '$pwd_hash'";
+
+ }
+
+ } else {
+ $query = "SELECT id
+ FROM ttrss_users WHERE
+ login = '$login' AND (pwd_hash = '$pwd_hash1' OR
+ pwd_hash = '$pwd_hash2')";
+ }
+
+ $result = db_query($this->link, $query);
+
+ if (db_num_rows($result) == 1) {
+ return db_fetch_result($result, 0, "id");
+ }
+
+ return false;
+ }
+
+ function check_password($owner_uid, $password) {
+ $owner_uid = db_escape_string($owner_uid);
+
+ $result = db_query($this->link, "SELECT salt,login FROM ttrss_users WHERE
+ id = '$owner_uid'");
+
+ $salt = db_fetch_result($result, 0, "salt");
+ $login = db_fetch_result($result, 0, "login");
+
+ if (!$salt) {
+ $password_hash1 = encrypt_password($password);
+ $password_hash2 = encrypt_password($password, $login);
+
+ $query = "SELECT id FROM ttrss_users WHERE
+ id = '$owner_uid' AND (pwd_hash = '$password_hash1' OR
+ pwd_hash = '$password_hash2')";
+
+ } else {
+ $password_hash = encrypt_password($password, $salt, true);
+
+ $query = "SELECT id FROM ttrss_users WHERE
+ id = '$owner_uid' AND pwd_hash = '$password_hash'";
+ }
+
+ $result = db_query($this->link, $query);
+
+ return db_num_rows($result) != 0;
+ }
+
+ function change_password($owner_uid, $old_password, $new_password) {
+ $owner_uid = db_escape_string($owner_uid);
+
+ if ($this->check_password($owner_uid, $old_password)) {
+
+ $new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
+ $new_password_hash = encrypt_password($new_password, $new_salt, true);
+
+ db_query($this->link, "UPDATE ttrss_users SET
+ pwd_hash = '$new_password_hash', salt = '$new_salt', otp_enabled = false
+ WHERE id = '$owner_uid'");
+
+ $_SESSION["pwd_hash"] = $new_password_hash;
+
+ return __("Password has been changed.");
+ } else {
+ return "ERROR: ".__('Old password is incorrect.');
+ }
+ }
+}
+?>
+++ /dev/null
-<?php
-class Auth_Remote extends Plugin implements IAuthModule {
-
- private $link;
- 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->link = $host->get_link();
- $this->host = $host;
- $this->base = new Auth_Base($this->link);
-
- $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($this->link, "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"]);
-
- 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);
-
- 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($this->link, "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($this->link, "UPDATE ttrss_users SET email = '$email' WHERE id = " .
- $user_id);
- }
- }
-
- return $user_id;
- }
- }
-
- return false;
- }
-}
-
-?>
--- /dev/null
+<?php
+class Auth_Remote extends Plugin implements IAuthModule {
+
+ private $link;
+ 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->link = $host->get_link();
+ $this->host = $host;
+ $this->base = new Auth_Base($this->link);
+
+ $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($this->link, "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"]);
+
+ 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);
+
+ 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($this->link, "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($this->link, "UPDATE ttrss_users SET email = '$email' WHERE id = " .
+ $user_id);
+ }
+ }
+
+ return $user_id;
+ }
+ }
+
+ return false;
+ }
+}
+
+?>
+++ /dev/null
-<?php
-class Digest extends Plugin implements IHandler {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Digest mode for tt-rss (tablet friendly UI)",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_handler("digest", "*", $this);
- }
-
- function index() {
- header("Content-type: text/html; charset=utf-8");
-
- login_sequence($this->link);
-
- global $link;
- $link = $this->link;
-
- require_once dirname(__FILE__) . "/digest_body.php";
- }
-
- /* function get_js() {
- return file_get_contents(dirname(__FILE__) . "/digest.js");
- } */
-
- function csrf_ignore($method) {
- return in_array($method, array("index"));
- }
-
- function before($method) {
- return true;
- }
-
- function after() {
-
- }
-
- function digestgetcontents() {
- $article_id = db_escape_string($_REQUEST['article_id']);
-
- $result = db_query($this->link, "SELECT content,title,link,marked,published
- FROM ttrss_entries, ttrss_user_entries
- WHERE id = '$article_id' AND ref_id = id AND owner_uid = ".$_SESSION['uid']);
-
- $content = sanitize($this->link, db_fetch_result($result, 0, "content"));
- $title = strip_tags(db_fetch_result($result, 0, "title"));
- $article_url = htmlspecialchars(db_fetch_result($result, 0, "link"));
- $marked = sql_bool_to_bool(db_fetch_result($result, 0, "marked"));
- $published = sql_bool_to_bool(db_fetch_result($result, 0, "published"));
-
- print json_encode(array("article" =>
- array("id" => $article_id, "url" => $article_url,
- "tags" => get_article_tags($this->link, $article_id),
- "marked" => $marked, "published" => $published,
- "title" => $title, "content" => $content)));
- }
-
- function digestupdate() {
- $feed_id = db_escape_string($_REQUEST['feed_id']);
- $offset = db_escape_string($_REQUEST['offset']);
- $seq = db_escape_string($_REQUEST['seq']);
-
- if (!$feed_id) $feed_id = -4;
- if (!$offset) $offset = 0;
-
- $reply = array();
-
- $reply['seq'] = $seq;
-
- $headlines = api_get_headlines($this->link, $feed_id, 30, $offset,
- '', ($feed_id == -4), true, false, "unread", "updated DESC", 0, 0);
-
- $reply['headlines'] = array();
- $reply['headlines']['title'] = getFeedTitle($this->link, $feed_id);
- $reply['headlines']['content'] = $headlines;
-
- print json_encode($reply);
- }
-
- function digestinit() {
- $tmp_feeds = api_get_feeds($this->link, -4, true, false, 0);
-
- $feeds = array();
-
- foreach ($tmp_feeds as $f) {
- if ($f['id'] > 0 || $f['id'] == -4) array_push($feeds, $f);
- }
-
- print json_encode(array("feeds" => $feeds));
- }
-
-}
-?>
--- /dev/null
+<?php
+class Digest extends Plugin implements IHandler {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Digest mode for tt-rss (tablet friendly UI)",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_handler("digest", "*", $this);
+ }
+
+ function index() {
+ header("Content-type: text/html; charset=utf-8");
+
+ login_sequence($this->link);
+
+ global $link;
+ $link = $this->link;
+
+ require_once dirname(__FILE__) . "/digest_body.php";
+ }
+
+ /* function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/digest.js");
+ } */
+
+ function csrf_ignore($method) {
+ return in_array($method, array("index"));
+ }
+
+ function before($method) {
+ return true;
+ }
+
+ function after() {
+
+ }
+
+ function digestgetcontents() {
+ $article_id = db_escape_string($_REQUEST['article_id']);
+
+ $result = db_query($this->link, "SELECT content,title,link,marked,published
+ FROM ttrss_entries, ttrss_user_entries
+ WHERE id = '$article_id' AND ref_id = id AND owner_uid = ".$_SESSION['uid']);
+
+ $content = sanitize($this->link, db_fetch_result($result, 0, "content"));
+ $title = strip_tags(db_fetch_result($result, 0, "title"));
+ $article_url = htmlspecialchars(db_fetch_result($result, 0, "link"));
+ $marked = sql_bool_to_bool(db_fetch_result($result, 0, "marked"));
+ $published = sql_bool_to_bool(db_fetch_result($result, 0, "published"));
+
+ print json_encode(array("article" =>
+ array("id" => $article_id, "url" => $article_url,
+ "tags" => get_article_tags($this->link, $article_id),
+ "marked" => $marked, "published" => $published,
+ "title" => $title, "content" => $content)));
+ }
+
+ function digestupdate() {
+ $feed_id = db_escape_string($_REQUEST['feed_id']);
+ $offset = db_escape_string($_REQUEST['offset']);
+ $seq = db_escape_string($_REQUEST['seq']);
+
+ if (!$feed_id) $feed_id = -4;
+ if (!$offset) $offset = 0;
+
+ $reply = array();
+
+ $reply['seq'] = $seq;
+
+ $headlines = api_get_headlines($this->link, $feed_id, 30, $offset,
+ '', ($feed_id == -4), true, false, "unread", "updated DESC", 0, 0);
+
+ $reply['headlines'] = array();
+ $reply['headlines']['title'] = getFeedTitle($this->link, $feed_id);
+ $reply['headlines']['content'] = $headlines;
+
+ print json_encode($reply);
+ }
+
+ function digestinit() {
+ $tmp_feeds = api_get_feeds($this->link, -4, true, false, 0);
+
+ $feeds = array();
+
+ foreach ($tmp_feeds as $f) {
+ if ($f['id'] > 0 || $f['id'] == -4) array_push($feeds, $f);
+ }
+
+ print json_encode(array("feeds" => $feeds));
+ }
+
+}
+?>
+++ /dev/null
-<?php
-class Example extends Plugin {
-
- // Demonstrates how to add a separate panel to the preferences screen and inject Javascript/save data using Dojo forms.
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Example plugin #1",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_PREFS_TAB, $this);
- }
-
- function save() {
- $example_value = db_escape_string($_POST["example_value"]);
-
- $this->host->set($this, "example", $example_value);
-
- echo "Value set to $example_value";
- }
-
- function get_prefs_js() {
- return file_get_contents(dirname(__FILE__) . "/example.js");
- }
-
- function hook_prefs_tab($args) {
- if ($args != "prefPrefs") return;
-
- print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Example Pane")."\">";
-
- print "<br/>";
-
-// print_r($this->host->set($this, "example", rand(0,100)));
-// print_r($this->host->get_all($this));
-
- $value = $this->host->get($this, "example");
-
- print "<form dojoType=\"dijit.form.Form\">";
-
- print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
- evt.preventDefault();
- if (this.validate()) {
- console.log(dojo.objectToQuery(this.getValues()));
- new Ajax.Request('backend.php', {
- parameters: dojo.objectToQuery(this.getValues()),
- onComplete: function(transport) {
- notify_info(transport.responseText);
- }
- });
- //this.reset();
- }
- </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=\"example\">";
-
- print "<table width=\"100%\" class=\"prefPrefsList\">";
-
- print "<tr><td width=\"40%\">".__("Sample value")."</td>";
- print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"example_value\" value=\"$value\"></td></tr>";
-
- print "</table>";
-
- print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
- __("Set value")."</button>";
-
- print "</form>";
-
- print "</div>"; #pane
- }
-}
-?>
--- /dev/null
+<?php
+class Example extends Plugin {
+
+ // Demonstrates how to add a separate panel to the preferences screen and inject Javascript/save data using Dojo forms.
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example plugin #1",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_PREFS_TAB, $this);
+ }
+
+ function save() {
+ $example_value = db_escape_string($_POST["example_value"]);
+
+ $this->host->set($this, "example", $example_value);
+
+ echo "Value set to $example_value";
+ }
+
+ function get_prefs_js() {
+ return file_get_contents(dirname(__FILE__) . "/example.js");
+ }
+
+ function hook_prefs_tab($args) {
+ if ($args != "prefPrefs") return;
+
+ print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Example Pane")."\">";
+
+ print "<br/>";
+
+// print_r($this->host->set($this, "example", rand(0,100)));
+// print_r($this->host->get_all($this));
+
+ $value = $this->host->get($this, "example");
+
+ print "<form dojoType=\"dijit.form.Form\">";
+
+ print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
+ evt.preventDefault();
+ if (this.validate()) {
+ console.log(dojo.objectToQuery(this.getValues()));
+ new Ajax.Request('backend.php', {
+ parameters: dojo.objectToQuery(this.getValues()),
+ onComplete: function(transport) {
+ notify_info(transport.responseText);
+ }
+ });
+ //this.reset();
+ }
+ </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=\"example\">";
+
+ print "<table width=\"100%\" class=\"prefPrefsList\">";
+
+ print "<tr><td width=\"40%\">".__("Sample value")."</td>";
+ print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"example_value\" value=\"$value\"></td></tr>";
+
+ print "</table>";
+
+ print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
+ __("Set value")."</button>";
+
+ print "</form>";
+
+ print "</div>"; #pane
+ }
+}
+?>
+++ /dev/null
-<?php
-class Example_Feed extends Plugin {
-
- // Demonstrates how to query data from the parsed feed object (SimplePie)
- // don't enable unless debugging feed through f D hotkey or manually.
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Example feed plugin",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_FEED_PARSED, $this);
- }
-
- function hook_feed_parsed($feed) {
- _debug("I'm a little feed short and stout, here's my title: " . $feed->get_title());
- _debug("... here's my link element: " . $feed->get_link());
- }
-}
-?>
--- /dev/null
+<?php
+class Example_Feed extends Plugin {
+
+ // Demonstrates how to query data from the parsed feed object (SimplePie)
+ // don't enable unless debugging feed through f D hotkey or manually.
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example feed plugin",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_FEED_PARSED, $this);
+ }
+
+ function hook_feed_parsed($feed) {
+ _debug("I'm a little feed short and stout, here's my title: " . $feed->get_title());
+ _debug("... here's my link element: " . $feed->get_link());
+ }
+}
+?>
+++ /dev/null
-<?php
-class Example_Routing extends Plugin implements IHandler {
-
- // Demonstrates adding a custom handler and method:
- // backend.php?op=test&method=example
- // and masking a system builtin public method:
- // public.php?op=getUnread
-
- // Plugin class must implelement IHandler interface and has
- // a public method of same name as being registered.
- //
- // Any system method may be masked by plugins. You can mask
- // entire handler by supplying "*" instead of a method name.
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Example routing plugin",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_handler("test", "example", $this);
- $host->add_handler("public", "getunread", $this);
- }
-
- function getunread() {
- print rand(0,100); # yeah right
- }
-
- function example() {
- print "example method called";
- }
-
- function csrf_ignore($method) {
- return true;
- }
-
- function before($method) {
- return true;
- }
-
- function after() {
- return true;
- }
-
-}
-?>
--- /dev/null
+<?php
+class Example_Routing extends Plugin implements IHandler {
+
+ // Demonstrates adding a custom handler and method:
+ // backend.php?op=test&method=example
+ // and masking a system builtin public method:
+ // public.php?op=getUnread
+
+ // Plugin class must implelement IHandler interface and has
+ // a public method of same name as being registered.
+ //
+ // Any system method may be masked by plugins. You can mask
+ // entire handler by supplying "*" instead of a method name.
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Example routing plugin",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_handler("test", "example", $this);
+ $host->add_handler("public", "getunread", $this);
+ }
+
+ function getunread() {
+ print rand(0,100); # yeah right
+ }
+
+ function example() {
+ print "example method called";
+ }
+
+ function csrf_ignore($method) {
+ return true;
+ }
+
+ function before($method) {
+ return true;
+ }
+
+ function after() {
+ return true;
+ }
+
+}
+?>
+++ /dev/null
-<?php
-class Flattr extends Plugin {
- private $link;
- private $host;
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function about() {
- return array(1.0,
- "Share articles on Flattr",
- "Nic Honing");
- }
-
- function hook_article_button($line) {
-
- $article_id = $line["id"];
-
- $result = db_query($this->link, "SELECT link
- FROM ttrss_entries, ttrss_user_entries
- WHERE id = '$article_id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
-
- if (db_num_rows($result) != 0) {
- $article_link = db_fetch_result($result, 0, 'link');
- }
-
- $response = null;
- if ($article_link) {
- $encoded = urlencode($article_link);
- $r = file_get_contents("https://api.flattr.com/rest/v2/things/lookup/?url=$encoded");
- $response = json_decode($r, true);
- }
-
- $rv = null;
- if ($response and array_key_exists('link', $response)) {
- $rv = "<a id='flattr' href='" . $response['link'] . "'>
- <img src=\"".theme_image($this->link, 'plugins/flattr/flattr.png')."\"
- class='tagsPic' style=\"cursor : pointer\"
- title='".__('Flattr article')."'>
- </a>";
- } else {
- $rv = "";
- }
-
- return $rv;
- }
-}
-?>
--- /dev/null
+<?php
+class Flattr extends Plugin {
+ private $link;
+ private $host;
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function about() {
+ return array(1.0,
+ "Share articles on Flattr",
+ "Nic Honing");
+ }
+
+ function hook_article_button($line) {
+
+ $article_id = $line["id"];
+
+ $result = db_query($this->link, "SELECT link
+ FROM ttrss_entries, ttrss_user_entries
+ WHERE id = '$article_id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
+
+ if (db_num_rows($result) != 0) {
+ $article_link = db_fetch_result($result, 0, 'link');
+ }
+
+ $response = null;
+ if ($article_link) {
+ $encoded = urlencode($article_link);
+ $r = file_get_contents("https://api.flattr.com/rest/v2/things/lookup/?url=$encoded");
+ $response = json_decode($r, true);
+ }
+
+ $rv = null;
+ if ($response and array_key_exists('link', $response)) {
+ $rv = "<a id='flattr' href='" . $response['link'] . "'>
+ <img src=\"".theme_image($this->link, 'plugins/flattr/flattr.png')."\"
+ class='tagsPic' style=\"cursor : pointer\"
+ title='".__('Flattr article')."'>
+ </a>";
+ } else {
+ $rv = "";
+ }
+
+ return $rv;
+ }
+}
+?>
+++ /dev/null
-<?php
-class GooglePlus extends Plugin {
- private $link;
- private $host;
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function about() {
- return array(1.0,
- "Share article on Google+",
- "homolibere");
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/googleplus.js");
- }
-
- function hook_article_button($line) {
- $article_id = $line["id"];
-
- $rv = "<img src=\"".theme_image($this->link, 'plugins/googleplus/googleplus.png')."\"
- class='tagsPic' style=\"cursor : pointer\"
- onclick=\"shareArticleToGooglePlus($article_id)\"
- title='".__('Share on Google+')."'>";
-
- return $rv;
- }
-
- function getInfo() {
- $id = db_escape_string($_REQUEST['id']);
-
- $result = db_query($this->link, "SELECT title, link
- FROM ttrss_entries, ttrss_user_entries
- WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
-
- if (db_num_rows($result) != 0) {
- $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
- 100, '...');
- $article_link = db_fetch_result($result, 0, 'link');
- }
-
- print json_encode(array("title" => $title, "link" => $article_link,
- "id" => $id));
- }
-
-
-}
-?>
--- /dev/null
+<?php
+class GooglePlus extends Plugin {
+ private $link;
+ private $host;
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function about() {
+ return array(1.0,
+ "Share article on Google+",
+ "homolibere");
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/googleplus.js");
+ }
+
+ function hook_article_button($line) {
+ $article_id = $line["id"];
+
+ $rv = "<img src=\"".theme_image($this->link, 'plugins/googleplus/googleplus.png')."\"
+ class='tagsPic' style=\"cursor : pointer\"
+ onclick=\"shareArticleToGooglePlus($article_id)\"
+ title='".__('Share on Google+')."'>";
+
+ return $rv;
+ }
+
+ function getInfo() {
+ $id = db_escape_string($_REQUEST['id']);
+
+ $result = db_query($this->link, "SELECT title, link
+ FROM ttrss_entries, ttrss_user_entries
+ WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
+
+ if (db_num_rows($result) != 0) {
+ $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
+ 100, '...');
+ $article_link = db_fetch_result($result, 0, 'link');
+ }
+
+ print json_encode(array("title" => $title, "link" => $article_link,
+ "id" => $id));
+ }
+
+
+}
+?>
+++ /dev/null
-<?php
-class Identica extends Plugin {
- private $link;
- private $host;
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function about() {
- return array(1.0,
- "Share articles on Identi.ca",
- "fox");
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/identica.js");
- }
-
- function hook_article_button($line) {
- $article_id = $line["id"];
-
- $rv = "<img src=\"".theme_image($this->link, 'plugins/identica/identica.png')."\"
- class='tagsPic' style=\"cursor : pointer\"
- onclick=\"shareArticleToIdentica($article_id)\"
- title='".__('Share on identi.ca')."'>";
-
- return $rv;
- }
-
- function getInfo() {
- $id = db_escape_string($_REQUEST['id']);
-
- $result = db_query($this->link, "SELECT title, link
- FROM ttrss_entries, ttrss_user_entries
- WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
-
- if (db_num_rows($result) != 0) {
- $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
- 100, '...');
- $article_link = db_fetch_result($result, 0, 'link');
- }
-
- print json_encode(array("title" => $title, "link" => $article_link,
- "id" => $id));
- }
-
-
-}
-?>
--- /dev/null
+<?php
+class Identica extends Plugin {
+ private $link;
+ private $host;
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function about() {
+ return array(1.0,
+ "Share articles on Identi.ca",
+ "fox");
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/identica.js");
+ }
+
+ function hook_article_button($line) {
+ $article_id = $line["id"];
+
+ $rv = "<img src=\"".theme_image($this->link, 'plugins/identica/identica.png')."\"
+ class='tagsPic' style=\"cursor : pointer\"
+ onclick=\"shareArticleToIdentica($article_id)\"
+ title='".__('Share on identi.ca')."'>";
+
+ return $rv;
+ }
+
+ function getInfo() {
+ $id = db_escape_string($_REQUEST['id']);
+
+ $result = db_query($this->link, "SELECT title, link
+ FROM ttrss_entries, ttrss_user_entries
+ WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
+
+ if (db_num_rows($result) != 0) {
+ $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
+ 100, '...');
+ $article_link = db_fetch_result($result, 0, 'link');
+ }
+
+ print json_encode(array("title" => $title, "link" => $article_link,
+ "id" => $id));
+ }
+
+
+}
+?>
+++ /dev/null
-<?php
-class Import_Export extends Plugin implements IHandler {
-
- private $link;
- private $host;
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_PREFS_TAB, $this);
- $host->add_command("xml-import", "USER FILE: import articles from XML", $this);
- }
-
- function about() {
- return array(1.0,
- "Imports and exports user data using neutral XML format",
- "fox");
- }
-
- function xml_import($args) {
- array_shift($args);
-
- $username = $args[count($args) - 2];
- $filename = $args[count($args) - 1];
-
- if (!$username) {
- print "error: please specify username.\n";
- return;
- }
-
- if (!is_file($filename)) {
- print "error: input filename ($filename) doesn't exist.\n";
- return;
- }
-
- _debug("importing $filename for user $username...\n");
-
- $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE login = '$username'");
-
- if (db_num_rows($result) == 0) {
- print "error: could not find user $username.\n";
- return;
- }
-
- $owner_uid = db_fetch_result($result, 0, "id");
-
- $this->perform_data_import($this->link, $filename, $owner_uid);
- }
-
- function save() {
- $example_value = db_escape_string($_POST["example_value"]);
-
- echo "Value set to $example_value (not really)";
- }
-
- function get_prefs_js() {
- return file_get_contents(dirname(__FILE__) . "/import_export.js");
- }
-
- function hook_prefs_tab($args) {
- if ($args != "prefFeeds") return;
-
- print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Import and export')."\">";
-
- 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\"
- name=\"data_upload_iframe\" onload=\"dataImportComplete(this)\"
- style=\"width: 400px; height: 100px; display: none;\"></iframe>";
-
- print "<form name=\"import_form\" style='display : block' target=\"data_upload_iframe\"
- enctype=\"multipart/form-data\" method=\"POST\"
- action=\"backend.php\">
- <input id=\"export_file\" name=\"export_file\" type=\"file\">
- <input type=\"hidden\" name=\"op\" value=\"pluginhandler\">
- <input type=\"hidden\" name=\"plugin\" value=\"import_export\">
- <input type=\"hidden\" name=\"method\" value=\"dataimport\">
- <button dojoType=\"dijit.form.Button\" onclick=\"return importData();\" type=\"submit\">" .
- __('Import') . "</button>";
-
-
- print "</div>"; # pane
- }
-
- function csrf_ignore($method) {
- return in_array($method, array("exportget"));
- }
-
- function before($method) {
- return $_SESSION["uid"] != false;
- }
-
- function after() {
- return true;
- }
-
- function exportget() {
- $exportname = CACHE_DIR . "/export/" .
- sha1($_SESSION['uid'] . $_SESSION['login']) . ".xml";
-
- if (file_exists($exportname)) {
- header("Content-type: text/xml");
-
- if (function_exists('gzencode')) {
- header("Content-Disposition: attachment; filename=TinyTinyRSS_exported.xml.gz");
- echo gzencode(file_get_contents($exportname));
- } else {
- header("Content-Disposition: attachment; filename=TinyTinyRSS_exported.xml");
- echo file_get_contents($exportname);
- }
- } else {
- echo "File not found.";
- }
- }
-
- function exportrun() {
- $offset = (int) db_escape_string($_REQUEST['offset']);
- $exported = 0;
- $limit = 250;
-
- if ($offset < 10000 && is_writable(CACHE_DIR . "/export")) {
- $result = db_query($this->link, "SELECT
- ttrss_entries.guid,
- ttrss_entries.title,
- content,
- marked,
- published,
- score,
- note,
- link,
- tag_cache,
- label_cache,
- ttrss_feeds.title AS feed_title,
- ttrss_feeds.feed_url AS feed_url,
- ttrss_entries.updated
- FROM
- ttrss_user_entries LEFT JOIN ttrss_feeds ON (ttrss_feeds.id = feed_id),
- ttrss_entries
- WHERE
- (marked = true OR feed_id IS NULL) AND
- ref_id = ttrss_entries.id AND
- ttrss_user_entries.owner_uid = " . $_SESSION['uid'] . "
- ORDER BY ttrss_entries.id LIMIT $limit OFFSET $offset");
-
- $exportname = sha1($_SESSION['uid'] . $_SESSION['login']);
-
- if ($offset == 0) {
- $fp = fopen(CACHE_DIR . "/export/$exportname.xml", "w");
- fputs($fp, "<articles schema-version=\"".SCHEMA_VERSION."\">");
- } else {
- $fp = fopen(CACHE_DIR . "/export/$exportname.xml", "a");
- }
-
- if ($fp) {
-
- while ($line = db_fetch_assoc($result)) {
- fputs($fp, "<article>");
-
- foreach ($line as $k => $v) {
- fputs($fp, "<$k><![CDATA[$v]]></$k>");
- }
-
- fputs($fp, "</article>");
- }
-
- $exported = db_num_rows($result);
-
- if ($exported < $limit && $exported > 0) {
- fputs($fp, "</articles>");
- }
-
- fclose($fp);
- }
-
- }
-
- print json_encode(array("exported" => $exported));
- }
-
- function perform_data_import($link, $filename, $owner_uid) {
-
- $num_imported = 0;
- $num_processed = 0;
- $num_feeds_created = 0;
-
- $doc = @DOMDocument::load($filename);
-
- if (!$doc) {
- $contents = file_get_contents($filename);
-
- if ($contents) {
- $data = @gzuncompress($contents);
- }
-
- if (!$data) {
- $data = @gzdecode($contents);
- }
-
- if ($data)
- $doc = DOMDocument::loadXML($data);
- }
-
- if ($doc) {
-
- $xpath = new DOMXpath($doc);
-
- $container = $doc->firstChild;
-
- if ($container && $container->hasAttribute('schema-version')) {
- $schema_version = $container->getAttribute('schema-version');
-
- if ($schema_version != SCHEMA_VERSION) {
- print "<p>" .__("Could not import: incorrect schema version.") . "</p>";
- return;
- }
-
- } else {
- print "<p>" . __("Could not import: unrecognized document format.") . "</p>";
- return;
- }
-
- $articles = $xpath->query("//article");
-
- foreach ($articles as $article_node) {
- if ($article_node->childNodes) {
-
- $ref_id = 0;
-
- $article = array();
-
- foreach ($article_node->childNodes as $child) {
- if ($child->nodeName != 'label_cache')
- $article[$child->nodeName] = db_escape_string($child->nodeValue);
- else
- $article[$child->nodeName] = $child->nodeValue;
- }
-
- //print_r($article);
-
- if ($article['guid']) {
-
- ++$num_processed;
-
- //db_query($link, "BEGIN");
-
- //print 'GUID:' . $article['guid'] . "\n";
-
- $result = db_query($link, "SELECT id FROM ttrss_entries
- WHERE guid = '".$article['guid']."'");
-
- if (db_num_rows($result) == 0) {
-
- $result = db_query($link,
- "INSERT INTO ttrss_entries
- (title,
- guid,
- link,
- updated,
- content,
- content_hash,
- no_orig_date,
- date_updated,
- date_entered,
- comments,
- num_comments,
- author)
- VALUES
- ('".$article['title']."',
- '".$article['guid']."',
- '".$article['link']."',
- '".$article['updated']."',
- '".$article['content']."',
- '".sha1($article['content'])."',
- false,
- NOW(),
- NOW(),
- '',
- '0',
- '')");
-
- $result = db_query($link, "SELECT id FROM ttrss_entries
- WHERE guid = '".$article['guid']."'");
-
- if (db_num_rows($result) != 0) {
- $ref_id = db_fetch_result($result, 0, "id");
- }
-
- } else {
- $ref_id = db_fetch_result($result, 0, "id");
- }
-
- //print "Got ref ID: $ref_id\n";
-
- if ($ref_id) {
-
- $feed_url = $article['feed_url'];
- $feed_title = $article['feed_title'];
-
- $feed = 'NULL';
-
- if ($feed_url && $feed_title) {
- $result = db_query($link, "SELECT id FROM ttrss_feeds
- WHERE feed_url = '$feed_url' AND owner_uid = '$owner_uid'");
-
- if (db_num_rows($result) != 0) {
- $feed = db_fetch_result($result, 0, "id");
- } else {
- // try autocreating feed in Uncategorized...
-
- $result = db_query($link, "INSERT INTO ttrss_feeds (owner_uid,
- feed_url, title) VALUES ($owner_uid, '$feed_url', '$feed_title')");
-
- $result = db_query($link, "SELECT id FROM ttrss_feeds
- WHERE feed_url = '$feed_url' AND owner_uid = '$owner_uid'");
-
- if (db_num_rows($result) != 0) {
- ++$num_feeds_created;
-
- $feed = db_fetch_result($result, 0, "id");
- }
- }
- }
-
- if ($feed != 'NULL')
- $feed_qpart = "feed_id = $feed";
- else
- $feed_qpart = "feed_id IS NULL";
-
- //print "$ref_id / $feed / " . $article['title'] . "\n";
-
- $result = db_query($link, "SELECT int_id FROM ttrss_user_entries
- WHERE ref_id = '$ref_id' AND owner_uid = '$owner_uid' AND $feed_qpart");
-
- if (db_num_rows($result) == 0) {
-
- $marked = bool_to_sql_bool(sql_bool_to_bool($article['marked']));
- $published = bool_to_sql_bool(sql_bool_to_bool($article['published']));
- $score = (int) $article['score'];
-
- $tag_cache = $article['tag_cache'];
- $label_cache = db_escape_string($article['label_cache']);
- $note = $article['note'];
-
- //print "Importing " . $article['title'] . "<br/>";
-
- ++$num_imported;
-
- $result = db_query($link,
- "INSERT INTO ttrss_user_entries
- (ref_id, owner_uid, feed_id, unread, last_read, marked,
- published, score, tag_cache, label_cache, uuid, note)
- VALUES ($ref_id, $owner_uid, $feed, false,
- NULL, $marked, $published, $score, '$tag_cache',
- '$label_cache', '', '$note')");
-
- $label_cache = json_decode($label_cache, true);
-
- if (is_array($label_cache) && $label_cache["no-labels"] != 1) {
- foreach ($label_cache as $label) {
-
- label_create($link, $label[1],
- $label[2], $label[3], $owner_uid);
-
- label_add_article($link, $ref_id, $label[1], $owner_uid);
-
- }
- }
-
- //db_query($link, "COMMIT");
- }
- }
- }
- }
- }
-
- print "<p>" .
- T_sprintf("Finished: %d articles processed, %d imported, %d feeds created.",
- $num_processed, $num_imported, $num_feeds_created) .
- "</p>";
-
- } else {
-
- print "<p>" . __("Could not load XML document.") . "</p>";
-
- }
- }
-
- function exportData() {
-
- print "<p style='text-align : center' id='export_status_message'>You need to prepare exported data first by clicking the button below.</p>";
-
- print "<div align='center'>";
- print "<button dojoType=\"dijit.form.Button\"
- onclick=\"dijit.byId('dataExportDlg').prepare()\">".
- __('Prepare data')."</button>";
-
- print "<button dojoType=\"dijit.form.Button\"
- onclick=\"dijit.byId('dataExportDlg').hide()\">".
- __('Close this window')."</button>";
-
- print "</div>";
-
-
- }
-
- function dataImport() {
- header("Content-Type: text/html"); # required for iframe
-
- print "<div style='text-align : center'>";
-
- if (is_file($_FILES['export_file']['tmp_name'])) {
-
- $this->perform_data_import($this->link, $_FILES['export_file']['tmp_name'], $_SESSION['uid']);
-
- } else {
- print "<p>" . T_sprintf("Could not upload file. You might need to adjust upload_max_filesize
- in PHP.ini (current value = %s)", ini_get("upload_max_filesize")) . " or use CLI import tool.</p>";
-
- }
-
- print "<button dojoType=\"dijit.form.Button\"
- onclick=\"dijit.byId('dataImportDlg').hide()\">".
- __('Close this window')."</button>";
-
- print "</div>";
-
- }
-
-
-}
-?>
--- /dev/null
+<?php
+class Import_Export extends Plugin implements IHandler {
+
+ private $link;
+ private $host;
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_PREFS_TAB, $this);
+ $host->add_command("xml-import", "USER FILE: import articles from XML", $this);
+ }
+
+ function about() {
+ return array(1.0,
+ "Imports and exports user data using neutral XML format",
+ "fox");
+ }
+
+ function xml_import($args) {
+ array_shift($args);
+
+ $username = $args[count($args) - 2];
+ $filename = $args[count($args) - 1];
+
+ if (!$username) {
+ print "error: please specify username.\n";
+ return;
+ }
+
+ if (!is_file($filename)) {
+ print "error: input filename ($filename) doesn't exist.\n";
+ return;
+ }
+
+ _debug("importing $filename for user $username...\n");
+
+ $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE login = '$username'");
+
+ if (db_num_rows($result) == 0) {
+ print "error: could not find user $username.\n";
+ return;
+ }
+
+ $owner_uid = db_fetch_result($result, 0, "id");
+
+ $this->perform_data_import($this->link, $filename, $owner_uid);
+ }
+
+ function save() {
+ $example_value = db_escape_string($_POST["example_value"]);
+
+ echo "Value set to $example_value (not really)";
+ }
+
+ function get_prefs_js() {
+ return file_get_contents(dirname(__FILE__) . "/import_export.js");
+ }
+
+ function hook_prefs_tab($args) {
+ if ($args != "prefFeeds") return;
+
+ print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Import and export')."\">";
+
+ 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\"
+ name=\"data_upload_iframe\" onload=\"dataImportComplete(this)\"
+ style=\"width: 400px; height: 100px; display: none;\"></iframe>";
+
+ print "<form name=\"import_form\" style='display : block' target=\"data_upload_iframe\"
+ enctype=\"multipart/form-data\" method=\"POST\"
+ action=\"backend.php\">
+ <input id=\"export_file\" name=\"export_file\" type=\"file\">
+ <input type=\"hidden\" name=\"op\" value=\"pluginhandler\">
+ <input type=\"hidden\" name=\"plugin\" value=\"import_export\">
+ <input type=\"hidden\" name=\"method\" value=\"dataimport\">
+ <button dojoType=\"dijit.form.Button\" onclick=\"return importData();\" type=\"submit\">" .
+ __('Import') . "</button>";
+
+
+ print "</div>"; # pane
+ }
+
+ function csrf_ignore($method) {
+ return in_array($method, array("exportget"));
+ }
+
+ function before($method) {
+ return $_SESSION["uid"] != false;
+ }
+
+ function after() {
+ return true;
+ }
+
+ function exportget() {
+ $exportname = CACHE_DIR . "/export/" .
+ sha1($_SESSION['uid'] . $_SESSION['login']) . ".xml";
+
+ if (file_exists($exportname)) {
+ header("Content-type: text/xml");
+
+ if (function_exists('gzencode')) {
+ header("Content-Disposition: attachment; filename=TinyTinyRSS_exported.xml.gz");
+ echo gzencode(file_get_contents($exportname));
+ } else {
+ header("Content-Disposition: attachment; filename=TinyTinyRSS_exported.xml");
+ echo file_get_contents($exportname);
+ }
+ } else {
+ echo "File not found.";
+ }
+ }
+
+ function exportrun() {
+ $offset = (int) db_escape_string($_REQUEST['offset']);
+ $exported = 0;
+ $limit = 250;
+
+ if ($offset < 10000 && is_writable(CACHE_DIR . "/export")) {
+ $result = db_query($this->link, "SELECT
+ ttrss_entries.guid,
+ ttrss_entries.title,
+ content,
+ marked,
+ published,
+ score,
+ note,
+ link,
+ tag_cache,
+ label_cache,
+ ttrss_feeds.title AS feed_title,
+ ttrss_feeds.feed_url AS feed_url,
+ ttrss_entries.updated
+ FROM
+ ttrss_user_entries LEFT JOIN ttrss_feeds ON (ttrss_feeds.id = feed_id),
+ ttrss_entries
+ WHERE
+ (marked = true OR feed_id IS NULL) AND
+ ref_id = ttrss_entries.id AND
+ ttrss_user_entries.owner_uid = " . $_SESSION['uid'] . "
+ ORDER BY ttrss_entries.id LIMIT $limit OFFSET $offset");
+
+ $exportname = sha1($_SESSION['uid'] . $_SESSION['login']);
+
+ if ($offset == 0) {
+ $fp = fopen(CACHE_DIR . "/export/$exportname.xml", "w");
+ fputs($fp, "<articles schema-version=\"".SCHEMA_VERSION."\">");
+ } else {
+ $fp = fopen(CACHE_DIR . "/export/$exportname.xml", "a");
+ }
+
+ if ($fp) {
+
+ while ($line = db_fetch_assoc($result)) {
+ fputs($fp, "<article>");
+
+ foreach ($line as $k => $v) {
+ fputs($fp, "<$k><![CDATA[$v]]></$k>");
+ }
+
+ fputs($fp, "</article>");
+ }
+
+ $exported = db_num_rows($result);
+
+ if ($exported < $limit && $exported > 0) {
+ fputs($fp, "</articles>");
+ }
+
+ fclose($fp);
+ }
+
+ }
+
+ print json_encode(array("exported" => $exported));
+ }
+
+ function perform_data_import($link, $filename, $owner_uid) {
+
+ $num_imported = 0;
+ $num_processed = 0;
+ $num_feeds_created = 0;
+
+ $doc = @DOMDocument::load($filename);
+
+ if (!$doc) {
+ $contents = file_get_contents($filename);
+
+ if ($contents) {
+ $data = @gzuncompress($contents);
+ }
+
+ if (!$data) {
+ $data = @gzdecode($contents);
+ }
+
+ if ($data)
+ $doc = DOMDocument::loadXML($data);
+ }
+
+ if ($doc) {
+
+ $xpath = new DOMXpath($doc);
+
+ $container = $doc->firstChild;
+
+ if ($container && $container->hasAttribute('schema-version')) {
+ $schema_version = $container->getAttribute('schema-version');
+
+ if ($schema_version != SCHEMA_VERSION) {
+ print "<p>" .__("Could not import: incorrect schema version.") . "</p>";
+ return;
+ }
+
+ } else {
+ print "<p>" . __("Could not import: unrecognized document format.") . "</p>";
+ return;
+ }
+
+ $articles = $xpath->query("//article");
+
+ foreach ($articles as $article_node) {
+ if ($article_node->childNodes) {
+
+ $ref_id = 0;
+
+ $article = array();
+
+ foreach ($article_node->childNodes as $child) {
+ if ($child->nodeName != 'label_cache')
+ $article[$child->nodeName] = db_escape_string($child->nodeValue);
+ else
+ $article[$child->nodeName] = $child->nodeValue;
+ }
+
+ //print_r($article);
+
+ if ($article['guid']) {
+
+ ++$num_processed;
+
+ //db_query($link, "BEGIN");
+
+ //print 'GUID:' . $article['guid'] . "\n";
+
+ $result = db_query($link, "SELECT id FROM ttrss_entries
+ WHERE guid = '".$article['guid']."'");
+
+ if (db_num_rows($result) == 0) {
+
+ $result = db_query($link,
+ "INSERT INTO ttrss_entries
+ (title,
+ guid,
+ link,
+ updated,
+ content,
+ content_hash,
+ no_orig_date,
+ date_updated,
+ date_entered,
+ comments,
+ num_comments,
+ author)
+ VALUES
+ ('".$article['title']."',
+ '".$article['guid']."',
+ '".$article['link']."',
+ '".$article['updated']."',
+ '".$article['content']."',
+ '".sha1($article['content'])."',
+ false,
+ NOW(),
+ NOW(),
+ '',
+ '0',
+ '')");
+
+ $result = db_query($link, "SELECT id FROM ttrss_entries
+ WHERE guid = '".$article['guid']."'");
+
+ if (db_num_rows($result) != 0) {
+ $ref_id = db_fetch_result($result, 0, "id");
+ }
+
+ } else {
+ $ref_id = db_fetch_result($result, 0, "id");
+ }
+
+ //print "Got ref ID: $ref_id\n";
+
+ if ($ref_id) {
+
+ $feed_url = $article['feed_url'];
+ $feed_title = $article['feed_title'];
+
+ $feed = 'NULL';
+
+ if ($feed_url && $feed_title) {
+ $result = db_query($link, "SELECT id FROM ttrss_feeds
+ WHERE feed_url = '$feed_url' AND owner_uid = '$owner_uid'");
+
+ if (db_num_rows($result) != 0) {
+ $feed = db_fetch_result($result, 0, "id");
+ } else {
+ // try autocreating feed in Uncategorized...
+
+ $result = db_query($link, "INSERT INTO ttrss_feeds (owner_uid,
+ feed_url, title) VALUES ($owner_uid, '$feed_url', '$feed_title')");
+
+ $result = db_query($link, "SELECT id FROM ttrss_feeds
+ WHERE feed_url = '$feed_url' AND owner_uid = '$owner_uid'");
+
+ if (db_num_rows($result) != 0) {
+ ++$num_feeds_created;
+
+ $feed = db_fetch_result($result, 0, "id");
+ }
+ }
+ }
+
+ if ($feed != 'NULL')
+ $feed_qpart = "feed_id = $feed";
+ else
+ $feed_qpart = "feed_id IS NULL";
+
+ //print "$ref_id / $feed / " . $article['title'] . "\n";
+
+ $result = db_query($link, "SELECT int_id FROM ttrss_user_entries
+ WHERE ref_id = '$ref_id' AND owner_uid = '$owner_uid' AND $feed_qpart");
+
+ if (db_num_rows($result) == 0) {
+
+ $marked = bool_to_sql_bool(sql_bool_to_bool($article['marked']));
+ $published = bool_to_sql_bool(sql_bool_to_bool($article['published']));
+ $score = (int) $article['score'];
+
+ $tag_cache = $article['tag_cache'];
+ $label_cache = db_escape_string($article['label_cache']);
+ $note = $article['note'];
+
+ //print "Importing " . $article['title'] . "<br/>";
+
+ ++$num_imported;
+
+ $result = db_query($link,
+ "INSERT INTO ttrss_user_entries
+ (ref_id, owner_uid, feed_id, unread, last_read, marked,
+ published, score, tag_cache, label_cache, uuid, note)
+ VALUES ($ref_id, $owner_uid, $feed, false,
+ NULL, $marked, $published, $score, '$tag_cache',
+ '$label_cache', '', '$note')");
+
+ $label_cache = json_decode($label_cache, true);
+
+ if (is_array($label_cache) && $label_cache["no-labels"] != 1) {
+ foreach ($label_cache as $label) {
+
+ label_create($link, $label[1],
+ $label[2], $label[3], $owner_uid);
+
+ label_add_article($link, $ref_id, $label[1], $owner_uid);
+
+ }
+ }
+
+ //db_query($link, "COMMIT");
+ }
+ }
+ }
+ }
+ }
+
+ print "<p>" .
+ T_sprintf("Finished: %d articles processed, %d imported, %d feeds created.",
+ $num_processed, $num_imported, $num_feeds_created) .
+ "</p>";
+
+ } else {
+
+ print "<p>" . __("Could not load XML document.") . "</p>";
+
+ }
+ }
+
+ function exportData() {
+
+ print "<p style='text-align : center' id='export_status_message'>You need to prepare exported data first by clicking the button below.</p>";
+
+ print "<div align='center'>";
+ print "<button dojoType=\"dijit.form.Button\"
+ onclick=\"dijit.byId('dataExportDlg').prepare()\">".
+ __('Prepare data')."</button>";
+
+ print "<button dojoType=\"dijit.form.Button\"
+ onclick=\"dijit.byId('dataExportDlg').hide()\">".
+ __('Close this window')."</button>";
+
+ print "</div>";
+
+
+ }
+
+ function dataImport() {
+ header("Content-Type: text/html"); # required for iframe
+
+ print "<div style='text-align : center'>";
+
+ if (is_file($_FILES['export_file']['tmp_name'])) {
+
+ $this->perform_data_import($this->link, $_FILES['export_file']['tmp_name'], $_SESSION['uid']);
+
+ } else {
+ print "<p>" . T_sprintf("Could not upload file. You might need to adjust upload_max_filesize
+ in PHP.ini (current value = %s)", ini_get("upload_max_filesize")) . " or use CLI import tool.</p>";
+
+ }
+
+ print "<button dojoType=\"dijit.form.Button\"
+ onclick=\"dijit.byId('dataImportDlg').hide()\">".
+ __('Close this window')."</button>";
+
+ print "</div>";
+
+ }
+
+
+}
+?>
--- /dev/null
+<?php
+class Instances extends Plugin implements IHandler {
+
+ private $link;
+ private $host;
+
+ private $status_codes = array(
+ 0 => "Connection failed",
+ 1 => "Success",
+ 2 => "Invalid object received",
+ 16 => "Access denied" );
+
+ function about() {
+ return array(1.0,
+ "Support for linking tt-rss instances together and sharing popular feeds.",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_PREFS_TABS, $this);
+ $host->add_handler("pref-instances", "*", $this);
+ $host->add_handler("public", "fbexport", $this);
+ $host->add_command("get-feeds", "receive popular feeds from linked instances", $this);
+ $host->add_hook($host::HOOK_UPDATE_TASK, $this);
+ }
+
+ function hook_update_task($args) {
+ _debug("Get linked feeds...");
+ $this->get_linked_feeds($this->link);
+ }
+
+ // Status codes:
+ // -1 - never connected
+ // 0 - no data received
+ // 1 - data received successfully
+ // 2 - did not receive valid data
+ // >10 - server error, code + 10 (e.g. 16 means server error 6)
+
+ function get_linked_feeds($link, $instance_id = false) {
+ if ($instance_id)
+ $instance_qpart = "id = '$instance_id' AND ";
+ else
+ $instance_qpart = "";
+
+ if (DB_TYPE == "pgsql") {
+ $date_qpart = "last_connected < NOW() - INTERVAL '6 hours'";
+ } else {
+ $date_qpart = "last_connected < DATE_SUB(NOW(), INTERVAL 6 HOUR)";
+ }
+
+ $result = db_query($link, "SELECT id, access_key, access_url FROM ttrss_linked_instances
+ WHERE $instance_qpart $date_qpart ORDER BY last_connected");
+
+ while ($line = db_fetch_assoc($result)) {
+ $id = $line['id'];
+
+ _debug("Updating: " . $line['access_url'] . " ($id)");
+
+ $fetch_url = $line['access_url'] . '/public.php?op=fbexport';
+ $post_query = 'key=' . $line['access_key'];
+
+ $feeds = fetch_file_contents($fetch_url, false, false, false, $post_query);
+
+ // try doing it the old way
+ if (!$feeds) {
+ $fetch_url = $line['access_url'] . '/backend.php?op=fbexport';
+ $feeds = fetch_file_contents($fetch_url, false, false, false, $post_query);
+ }
+
+ if ($feeds) {
+ $feeds = json_decode($feeds, true);
+
+ if ($feeds) {
+ if ($feeds['error']) {
+ $status = $feeds['error']['code'] + 10;
+
+ // access denied
+ if ($status == 16) {
+ db_query($link, "DELETE FROM ttrss_linked_feeds
+ WHERE instance_id = '$id'");
+ }
+ } else {
+ $status = 1;
+
+ if (count($feeds['feeds']) > 0) {
+
+ db_query($link, "DELETE FROM ttrss_linked_feeds
+ WHERE instance_id = '$id'");
+
+ foreach ($feeds['feeds'] as $feed) {
+ $feed_url = db_escape_string($feed['feed_url']);
+ $title = db_escape_string($feed['title']);
+ $subscribers = db_escape_string($feed['subscribers']);
+ $site_url = db_escape_string($feed['site_url']);
+
+ db_query($link, "INSERT INTO ttrss_linked_feeds
+ (feed_url, site_url, title, subscribers, instance_id, created, updated)
+ VALUES
+ ('$feed_url', '$site_url', '$title', '$subscribers', '$id', NOW(), NOW())");
+ }
+ } else {
+ // received 0 feeds, this might indicate that
+ // the instance on the other hand is rebuilding feedbrowser cache
+ // we will try again later
+
+ // TODO: maybe perform expiration based on updated here?
+ }
+
+ _debug("Processed " . count($feeds['feeds']) . " feeds.");
+ }
+ } else {
+ $status = 2;
+ }
+
+ } else {
+ $status = 0;
+ }
+
+ _debug("Status: $status");
+
+ db_query($link, "UPDATE ttrss_linked_instances SET
+ last_status_out = '$status', last_connected = NOW() WHERE id = '$id'");
+
+ }
+ }
+
+
+ function get_feeds() {
+ $this->get_linked_feeds($this->link, false);
+ }
+
+ function get_prefs_js() {
+ return file_get_contents(dirname(__FILE__) . "/instances.js");
+ }
+
+ function hook_prefs_tabs($args) {
+ if ($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) {
+ ?><div id="instanceConfigTab" dojoType="dijit.layout.ContentPane"
+ href="backend.php?op=pref-instances"
+ title="<?php echo __('Linked') ?>"></div><?php
+ }
+ }
+
+ function csrf_ignore($method) {
+ $csrf_ignored = array("index", "edit");
+
+ return array_search($method, $csrf_ignored) !== false;
+ }
+
+ function before($method) {
+ if ($_SESSION["uid"]) {
+ if ($_SESSION["access_level"] < 10) {
+ print __("Your access level is insufficient to open this tab.");
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ function after() {
+ return true;
+ }
+
+ function remove() {
+ $ids = db_escape_string($_REQUEST['ids']);
+
+ db_query($this->link, "DELETE FROM ttrss_linked_instances WHERE
+ id IN ($ids)");
+ }
+
+ function 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($this->link, "BEGIN");
+
+ $result = db_query($this->link, "SELECT id FROM ttrss_linked_instances
+ WHERE access_url = '$access_url'");
+
+ if (db_num_rows($result) == 0) {
+ db_query($this->link, "INSERT INTO ttrss_linked_instances
+ (access_url, access_key, last_connected, last_status_in, last_status_out)
+ VALUES
+ ('$access_url', '$access_key', '1970-01-01', -1, -1)");
+
+ }
+
+ db_query($this->link, "COMMIT");
+ }
+
+ function edit() {
+ $id = db_escape_string($_REQUEST["id"]);
+
+ $result = db_query($this->link, "SELECT * FROM ttrss_linked_instances WHERE
+ id = '$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=\"method\" 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\"
+ placeHolder=\"".__("Instance URL")."\"
+ regExp='^(http|https)://.*'
+ style=\"font-size : 16px; width: 20em\" name=\"access_url\"
+ value=\"$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\"
+ placeHolder=\"".__("Access key")."\" regExp='\w{40}'
+ style=\"width: 20em\" name=\"access_key\" id=\"instance_edit_key\"
+ value=\"$access_key\">";
+
+ print "<p class='insensitive'>" . __("Use one access key for both linked instances.");
+
+ print "</div>";
+
+ print "<div class=\"dlgButtons\">
+ <div style='float : left'>
+ <button dojoType=\"dijit.form.Button\"
+ onclick=\"return dijit.byId('instanceEditDlg').regenKey()\">".
+ __('Generate new key')."</button>
+ </div>
+ <button dojoType=\"dijit.form.Button\"
+ onclick=\"return dijit.byId('instanceEditDlg').execute()\">".
+ __('Save')."</button>
+ <button dojoType=\"dijit.form.Button\"
+ onclick=\"return dijit.byId('instanceEditDlg').hide()\"\">".
+ __('Cancel')."</button></div>";
+
+ }
+
+ function 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($this->link, "UPDATE ttrss_linked_instances SET
+ access_key = '$access_key', access_url = '$access_url',
+ last_connected = '1970-01-01'
+ WHERE id = '$id'");
+
+ }
+
+ 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')\"
+ dojoType=\"dijit.MenuItem\">".__('All')."</div>";
+ print "<div onclick=\"selectTableRows('prefInstanceList', 'none')\"
+ dojoType=\"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 *,
+ (SELECT COUNT(*) FROM ttrss_linked_feeds
+ WHERE instance_id = ttrss_linked_instances.id) AS num_feeds
+ FROM ttrss_linked_instances
+ ORDER 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\">
+ <td align='center' width=\"5%\"> </td>
+ <td width=''><a href=\"#\" onclick=\"updateInstanceList('access_url')\">".__('Instance URL')."</a></td>
+ <td width='20%'><a href=\"#\" onclick=\"updateInstanceList('access_key')\">".__('Access key')."</a></td>
+ <td width='10%'><a href=\"#\" onclick=\"updateUsersList('last_connected')\">".__('Last connected')."</a></td>
+ <td width='10%'><a href=\"#\" onclick=\"updateUsersList('last_status_out')\">".__('Status')."</a></td>
+ <td width='10%'><a href=\"#\" onclick=\"updateUsersList('num_feeds')\">".__('Stored feeds')."</a></td>
+ </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);'
+ type=\"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
+
+ global $pluginhost;
+ $pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB,
+ "hook_prefs_tab", "prefInstances");
+
+ print "</div>"; #container
+
+ }
+
+ function fbexport() {
+
+ $access_key = db_escape_string($_POST["key"]);
+
+ // TODO: rate limit checking using last_connected
+ $result = db_query($this->link, "SELECT id FROM ttrss_linked_instances
+ WHERE access_key = '$access_key'");
+
+ if (db_num_rows($result) == 1) {
+
+ $instance_id = db_fetch_result($result, 0, "id");
+
+ $result = db_query($this->link, "SELECT feed_url, site_url, title, subscribers
+ FROM ttrss_feedbrowser_cache ORDER BY subscribers DESC LIMIT 100");
+
+ $feeds = array();
+
+ while ($line = db_fetch_assoc($result)) {
+ array_push($feeds, $line);
+ }
+
+ db_query($this->link, "UPDATE ttrss_linked_instances SET
+ last_status_in = 1 WHERE id = '$instance_id'");
+
+ print json_encode(array("feeds" => $feeds));
+ } else {
+ print json_encode(array("error" => array("code" => 6)));
+ }
+ }
+
+
+}
+?>
+
+++ /dev/null
-<?php
-class Instances extends Plugin implements IHandler {
-
- private $link;
- private $host;
-
- private $status_codes = array(
- 0 => "Connection failed",
- 1 => "Success",
- 2 => "Invalid object received",
- 16 => "Access denied" );
-
- function about() {
- return array(1.0,
- "Support for linking tt-rss instances together and sharing popular feeds.",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_PREFS_TABS, $this);
- $host->add_handler("pref-instances", "*", $this);
- $host->add_handler("public", "fbexport", $this);
- $host->add_command("get-feeds", "receive popular feeds from linked instances", $this);
- $host->add_hook($host::HOOK_UPDATE_TASK, $this);
- }
-
- function hook_update_task($args) {
- _debug("Get linked feeds...");
- $this->get_linked_feeds($this->link);
- }
-
- // Status codes:
- // -1 - never connected
- // 0 - no data received
- // 1 - data received successfully
- // 2 - did not receive valid data
- // >10 - server error, code + 10 (e.g. 16 means server error 6)
-
- function get_linked_feeds($link, $instance_id = false) {
- if ($instance_id)
- $instance_qpart = "id = '$instance_id' AND ";
- else
- $instance_qpart = "";
-
- if (DB_TYPE == "pgsql") {
- $date_qpart = "last_connected < NOW() - INTERVAL '6 hours'";
- } else {
- $date_qpart = "last_connected < DATE_SUB(NOW(), INTERVAL 6 HOUR)";
- }
-
- $result = db_query($link, "SELECT id, access_key, access_url FROM ttrss_linked_instances
- WHERE $instance_qpart $date_qpart ORDER BY last_connected");
-
- while ($line = db_fetch_assoc($result)) {
- $id = $line['id'];
-
- _debug("Updating: " . $line['access_url'] . " ($id)");
-
- $fetch_url = $line['access_url'] . '/public.php?op=fbexport';
- $post_query = 'key=' . $line['access_key'];
-
- $feeds = fetch_file_contents($fetch_url, false, false, false, $post_query);
-
- // try doing it the old way
- if (!$feeds) {
- $fetch_url = $line['access_url'] . '/backend.php?op=fbexport';
- $feeds = fetch_file_contents($fetch_url, false, false, false, $post_query);
- }
-
- if ($feeds) {
- $feeds = json_decode($feeds, true);
-
- if ($feeds) {
- if ($feeds['error']) {
- $status = $feeds['error']['code'] + 10;
-
- // access denied
- if ($status == 16) {
- db_query($link, "DELETE FROM ttrss_linked_feeds
- WHERE instance_id = '$id'");
- }
- } else {
- $status = 1;
-
- if (count($feeds['feeds']) > 0) {
-
- db_query($link, "DELETE FROM ttrss_linked_feeds
- WHERE instance_id = '$id'");
-
- foreach ($feeds['feeds'] as $feed) {
- $feed_url = db_escape_string($feed['feed_url']);
- $title = db_escape_string($feed['title']);
- $subscribers = db_escape_string($feed['subscribers']);
- $site_url = db_escape_string($feed['site_url']);
-
- db_query($link, "INSERT INTO ttrss_linked_feeds
- (feed_url, site_url, title, subscribers, instance_id, created, updated)
- VALUES
- ('$feed_url', '$site_url', '$title', '$subscribers', '$id', NOW(), NOW())");
- }
- } else {
- // received 0 feeds, this might indicate that
- // the instance on the other hand is rebuilding feedbrowser cache
- // we will try again later
-
- // TODO: maybe perform expiration based on updated here?
- }
-
- _debug("Processed " . count($feeds['feeds']) . " feeds.");
- }
- } else {
- $status = 2;
- }
-
- } else {
- $status = 0;
- }
-
- _debug("Status: $status");
-
- db_query($link, "UPDATE ttrss_linked_instances SET
- last_status_out = '$status', last_connected = NOW() WHERE id = '$id'");
-
- }
- }
-
-
- function get_feeds() {
- $this->get_linked_feeds($this->link, false);
- }
-
- function get_prefs_js() {
- return file_get_contents(dirname(__FILE__) . "/instances.js");
- }
-
- function hook_prefs_tabs($args) {
- if ($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) {
- ?><div id="instanceConfigTab" dojoType="dijit.layout.ContentPane"
- href="backend.php?op=pref-instances"
- title="<?php echo __('Linked') ?>"></div><?php
- }
- }
-
- function csrf_ignore($method) {
- $csrf_ignored = array("index", "edit");
-
- return array_search($method, $csrf_ignored) !== false;
- }
-
- function before($method) {
- if ($_SESSION["uid"]) {
- if ($_SESSION["access_level"] < 10) {
- print __("Your access level is insufficient to open this tab.");
- return false;
- }
- return true;
- }
- return false;
- }
-
- function after() {
- return true;
- }
-
- function remove() {
- $ids = db_escape_string($_REQUEST['ids']);
-
- db_query($this->link, "DELETE FROM ttrss_linked_instances WHERE
- id IN ($ids)");
- }
-
- function 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($this->link, "BEGIN");
-
- $result = db_query($this->link, "SELECT id FROM ttrss_linked_instances
- WHERE access_url = '$access_url'");
-
- if (db_num_rows($result) == 0) {
- db_query($this->link, "INSERT INTO ttrss_linked_instances
- (access_url, access_key, last_connected, last_status_in, last_status_out)
- VALUES
- ('$access_url', '$access_key', '1970-01-01', -1, -1)");
-
- }
-
- db_query($this->link, "COMMIT");
- }
-
- function edit() {
- $id = db_escape_string($_REQUEST["id"]);
-
- $result = db_query($this->link, "SELECT * FROM ttrss_linked_instances WHERE
- id = '$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=\"method\" 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\"
- placeHolder=\"".__("Instance URL")."\"
- regExp='^(http|https)://.*'
- style=\"font-size : 16px; width: 20em\" name=\"access_url\"
- value=\"$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\"
- placeHolder=\"".__("Access key")."\" regExp='\w{40}'
- style=\"width: 20em\" name=\"access_key\" id=\"instance_edit_key\"
- value=\"$access_key\">";
-
- print "<p class='insensitive'>" . __("Use one access key for both linked instances.");
-
- print "</div>";
-
- print "<div class=\"dlgButtons\">
- <div style='float : left'>
- <button dojoType=\"dijit.form.Button\"
- onclick=\"return dijit.byId('instanceEditDlg').regenKey()\">".
- __('Generate new key')."</button>
- </div>
- <button dojoType=\"dijit.form.Button\"
- onclick=\"return dijit.byId('instanceEditDlg').execute()\">".
- __('Save')."</button>
- <button dojoType=\"dijit.form.Button\"
- onclick=\"return dijit.byId('instanceEditDlg').hide()\"\">".
- __('Cancel')."</button></div>";
-
- }
-
- function 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($this->link, "UPDATE ttrss_linked_instances SET
- access_key = '$access_key', access_url = '$access_url',
- last_connected = '1970-01-01'
- WHERE id = '$id'");
-
- }
-
- 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')\"
- dojoType=\"dijit.MenuItem\">".__('All')."</div>";
- print "<div onclick=\"selectTableRows('prefInstanceList', 'none')\"
- dojoType=\"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 *,
- (SELECT COUNT(*) FROM ttrss_linked_feeds
- WHERE instance_id = ttrss_linked_instances.id) AS num_feeds
- FROM ttrss_linked_instances
- ORDER 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\">
- <td align='center' width=\"5%\"> </td>
- <td width=''><a href=\"#\" onclick=\"updateInstanceList('access_url')\">".__('Instance URL')."</a></td>
- <td width='20%'><a href=\"#\" onclick=\"updateInstanceList('access_key')\">".__('Access key')."</a></td>
- <td width='10%'><a href=\"#\" onclick=\"updateUsersList('last_connected')\">".__('Last connected')."</a></td>
- <td width='10%'><a href=\"#\" onclick=\"updateUsersList('last_status_out')\">".__('Status')."</a></td>
- <td width='10%'><a href=\"#\" onclick=\"updateUsersList('num_feeds')\">".__('Stored feeds')."</a></td>
- </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);'
- type=\"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
-
- global $pluginhost;
- $pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB,
- "hook_prefs_tab", "prefInstances");
-
- print "</div>"; #container
-
- }
-
- function fbexport() {
-
- $access_key = db_escape_string($_POST["key"]);
-
- // TODO: rate limit checking using last_connected
- $result = db_query($this->link, "SELECT id FROM ttrss_linked_instances
- WHERE access_key = '$access_key'");
-
- if (db_num_rows($result) == 1) {
-
- $instance_id = db_fetch_result($result, 0, "id");
-
- $result = db_query($this->link, "SELECT feed_url, site_url, title, subscribers
- FROM ttrss_feedbrowser_cache ORDER BY subscribers DESC LIMIT 100");
-
- $feeds = array();
-
- while ($line = db_fetch_assoc($result)) {
- array_push($feeds, $line);
- }
-
- db_query($this->link, "UPDATE ttrss_linked_instances SET
- last_status_in = 1 WHERE id = '$instance_id'");
-
- print json_encode(array("feeds" => $feeds));
- } else {
- print json_encode(array("error" => array("code" => 6)));
- }
- }
-
-
-}
-?>
-
--- /dev/null
+<?php
+class Mail extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Share article via email",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/mail.js");
+ }
+
+ function hook_article_button($line) {
+ return "<img src=\"".theme_image($link, 'plugins/mail/mail.png')."\"
+ class='tagsPic' style=\"cursor : pointer\"
+ onclick=\"emailArticle(".$line["id"].")\"
+ alt='Zoom' title='".__('Forward by email')."'>";
+ }
+
+ function emailArticle() {
+
+ $param = db_escape_string($_REQUEST['param']);
+
+ $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=\"pluginhandler\">";
+ print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"mail\">";
+ print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"sendEmail\">";
+
+ $result = db_query($this->link, "SELECT email, full_name FROM ttrss_users WHERE
+ id = " . $_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"]);
+
+
+ $result = db_query($this->link, "SELECT link, content, title
+ FROM ttrss_user_entries, ttrss_entries WHERE id = ref_id AND
+ id 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;\"
+ value=\"$user_name <$user_email>\">";
+
+ print "</td></tr><tr><td>";
+
+ print __('To:');
+
+ print "</td><td>";
+
+ print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"true\"
+ style=\"width : 30em;\"
+ name=\"destination\" id=\"emailArticleDlg_destination\">";
+
+ print "<div class=\"autocomplete\" id=\"emailArticleDlg_dst_choices\"
+ style=\"z-index: 30; display : none\"></div>";
+
+ print "</td></tr><tr><td>";
+
+ print __('Subject:');
+
+ print "</td><td>";
+
+ print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"true\"
+ style=\"width : 30em;\"
+ name=\"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\"
+ name='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;
+ }
+
+ function sendEmail() {
+ $secretkey = $_REQUEST['secretkey'];
+
+ require_once 'lib/phpmailer/class.phpmailer.php';
+
+ $reply = array();
+
+ if ($_SESSION['email_secretkey'] &&
+ $secretkey == $_SESSION['email_secretkey']) {
+
+ $_SESSION['email_secretkey'] = '';
+
+ $destination = $_REQUEST['destination'];
+ $subject = $_REQUEST['subject'];
+ $content = $_REQUEST['content'];
+
+ $replyto = strip_tags($_SESSION['email_replyto']);
+ $fromname = strip_tags($_SESSION['email_fromname']);
+
+ $mail = new PHPMailer();
+
+ $mail->PluginDir = "lib/phpmailer/";
+ $mail->SetLanguage("en", "lib/phpmailer/language/");
+
+ $mail->CharSet = "UTF-8";
+
+ $mail->From = $replyto;
+ $mail->FromName = $fromname;
+ $mail->AddAddress($destination);
+
+ if (SMTP_HOST) {
+ $mail->Host = SMTP_HOST;
+ $mail->Mailer = "smtp";
+ $mail->SMTPAuth = SMTP_LOGIN != '';
+ $mail->Username = SMTP_LOGIN;
+ $mail->Password = SMTP_PASSWORD;
+ }
+
+ $mail->IsHTML(false);
+ $mail->Subject = $subject;
+ $mail->Body = $content;
+
+ $rc = $mail->Send();
+
+ if (!$rc) {
+ $reply['error'] = $mail->ErrorInfo;
+ } else {
+ save_email_address($this->link, db_escape_string($destination));
+ $reply['message'] = "UPDATE_COUNTERS";
+ }
+
+ } else {
+ $reply['error'] = "Not authorized.";
+ }
+
+ print json_encode($reply);
+ }
+
+ function completeEmails() {
+ $search = db_escape_string($_REQUEST["search"]);
+
+ print "<ul>";
+
+ foreach ($_SESSION['stored_emails'] as $email) {
+ if (strpos($email, $search) !== false) {
+ print "<li>$email</li>";
+ }
+ }
+
+ print "</ul>";
+ }
+
+
+}
+?>
+++ /dev/null
-<?php
-class Mail extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Share article via email",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/mail.js");
- }
-
- function hook_article_button($line) {
- return "<img src=\"".theme_image($link, 'plugins/mail/mail.png')."\"
- class='tagsPic' style=\"cursor : pointer\"
- onclick=\"emailArticle(".$line["id"].")\"
- alt='Zoom' title='".__('Forward by email')."'>";
- }
-
- function emailArticle() {
-
- $param = db_escape_string($_REQUEST['param']);
-
- $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=\"pluginhandler\">";
- print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"mail\">";
- print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"sendEmail\">";
-
- $result = db_query($this->link, "SELECT email, full_name FROM ttrss_users WHERE
- id = " . $_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"]);
-
-
- $result = db_query($this->link, "SELECT link, content, title
- FROM ttrss_user_entries, ttrss_entries WHERE id = ref_id AND
- id 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;\"
- value=\"$user_name <$user_email>\">";
-
- print "</td></tr><tr><td>";
-
- print __('To:');
-
- print "</td><td>";
-
- print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"true\"
- style=\"width : 30em;\"
- name=\"destination\" id=\"emailArticleDlg_destination\">";
-
- print "<div class=\"autocomplete\" id=\"emailArticleDlg_dst_choices\"
- style=\"z-index: 30; display : none\"></div>";
-
- print "</td></tr><tr><td>";
-
- print __('Subject:');
-
- print "</td><td>";
-
- print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"true\"
- style=\"width : 30em;\"
- name=\"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\"
- name='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;
- }
-
- function sendEmail() {
- $secretkey = $_REQUEST['secretkey'];
-
- require_once 'lib/phpmailer/class.phpmailer.php';
-
- $reply = array();
-
- if ($_SESSION['email_secretkey'] &&
- $secretkey == $_SESSION['email_secretkey']) {
-
- $_SESSION['email_secretkey'] = '';
-
- $destination = $_REQUEST['destination'];
- $subject = $_REQUEST['subject'];
- $content = $_REQUEST['content'];
-
- $replyto = strip_tags($_SESSION['email_replyto']);
- $fromname = strip_tags($_SESSION['email_fromname']);
-
- $mail = new PHPMailer();
-
- $mail->PluginDir = "lib/phpmailer/";
- $mail->SetLanguage("en", "lib/phpmailer/language/");
-
- $mail->CharSet = "UTF-8";
-
- $mail->From = $replyto;
- $mail->FromName = $fromname;
- $mail->AddAddress($destination);
-
- if (SMTP_HOST) {
- $mail->Host = SMTP_HOST;
- $mail->Mailer = "smtp";
- $mail->SMTPAuth = SMTP_LOGIN != '';
- $mail->Username = SMTP_LOGIN;
- $mail->Password = SMTP_PASSWORD;
- }
-
- $mail->IsHTML(false);
- $mail->Subject = $subject;
- $mail->Body = $content;
-
- $rc = $mail->Send();
-
- if (!$rc) {
- $reply['error'] = $mail->ErrorInfo;
- } else {
- save_email_address($this->link, db_escape_string($destination));
- $reply['message'] = "UPDATE_COUNTERS";
- }
-
- } else {
- $reply['error'] = "Not authorized.";
- }
-
- print json_encode($reply);
- }
-
- function completeEmails() {
- $search = db_escape_string($_REQUEST["search"]);
-
- print "<ul>";
-
- foreach ($_SESSION['stored_emails'] as $email) {
- if (strpos($email, $search) !== false) {
- print "<li>$email</li>";
- }
- }
-
- print "</ul>";
- }
-
-
-}
-?>
--- /dev/null
+<?php
+class Note extends Plugin {
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Adds support for setting article notes",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/note.js");
+ }
+
+
+ function hook_article_button($line) {
+ return "<img src=\"".theme_image($this->link, "plugins/note/note.png")."\"
+ style=\"cursor : pointer\" style=\"cursor : pointer\"
+ onclick=\"editArticleNote(".$line["id"].")\"
+ class='tagsPic' title='".__('Edit article note')."'>";
+ }
+
+ function edit() {
+ $param = db_escape_string($_REQUEST['param']);
+
+ $result = db_query($this->link, "SELECT note FROM ttrss_user_entries WHERE
+ ref_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=\"pluginhandler\">";
+ print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"setNote\">";
+ print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"note\">";
+
+ print "<table width='100%'><tr><td>";
+ print "<textarea dojoType=\"dijit.form.SimpleTextarea\"
+ style='font-size : 12px; width : 100%; height: 100px;'
+ placeHolder='body#ttrssMain { font-size : 14px; };'
+ name='note'>$note</textarea>";
+ print "</td></tr></table>";
+
+ print "<div class='dlgButtons'>";
+ print "<button dojoType=\"dijit.form.Button\"
+ onclick=\"dijit.byId('editNoteDlg').execute()\">".__('Save')."</button> ";
+ print "<button dojoType=\"dijit.form.Button\"
+ onclick=\"dijit.byId('editNoteDlg').hide()\">".__('Cancel')."</button>";
+ print "</div>";
+
+ }
+
+ function setNote() {
+ $id = db_escape_string($_REQUEST["id"]);
+ $note = trim(strip_tags(db_escape_string($_REQUEST["note"])));
+
+ db_query($this->link, "UPDATE ttrss_user_entries SET note = '$note'
+ WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
+
+ $formatted_note = format_article_note($id, $note);
+
+ print json_encode(array("note" => $formatted_note,
+ "raw_length" => mb_strlen($note)));
+ }
+
+}
+?>
+++ /dev/null
-<?php
-class Note extends Plugin {
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Adds support for setting article notes",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/note.js");
- }
-
-
- function hook_article_button($line) {
- return "<img src=\"".theme_image($this->link, "plugins/note/note.png")."\"
- style=\"cursor : pointer\" style=\"cursor : pointer\"
- onclick=\"editArticleNote(".$line["id"].")\"
- class='tagsPic' title='".__('Edit article note')."'>";
- }
-
- function edit() {
- $param = db_escape_string($_REQUEST['param']);
-
- $result = db_query($this->link, "SELECT note FROM ttrss_user_entries WHERE
- ref_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=\"pluginhandler\">";
- print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"setNote\">";
- print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"note\">";
-
- print "<table width='100%'><tr><td>";
- print "<textarea dojoType=\"dijit.form.SimpleTextarea\"
- style='font-size : 12px; width : 100%; height: 100px;'
- placeHolder='body#ttrssMain { font-size : 14px; };'
- name='note'>$note</textarea>";
- print "</td></tr></table>";
-
- print "<div class='dlgButtons'>";
- print "<button dojoType=\"dijit.form.Button\"
- onclick=\"dijit.byId('editNoteDlg').execute()\">".__('Save')."</button> ";
- print "<button dojoType=\"dijit.form.Button\"
- onclick=\"dijit.byId('editNoteDlg').hide()\">".__('Cancel')."</button>";
- print "</div>";
-
- }
-
- function setNote() {
- $id = db_escape_string($_REQUEST["id"]);
- $note = trim(strip_tags(db_escape_string($_REQUEST["note"])));
-
- db_query($this->link, "UPDATE ttrss_user_entries SET note = '$note'
- WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
-
- $formatted_note = format_article_note($id, $note);
-
- print json_encode(array("note" => $formatted_note,
- "raw_length" => mb_strlen($note)));
- }
-
-}
-?>
--- /dev/null
+<?php
+require_once "config.php";
+
+class OwnCloud extends Plugin {
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Adds support for OwnCloud ReadLater",
+ "cy8aer");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ $host->add_hook($host::HOOK_PREFS_TAB, $this);
+ }
+
+ function save() {
+ $owncloud_url = db_escape_string($_POST["owncloud_url"]);
+ $this->host->set($this, "owncloud", $owncloud_url);
+ echo "Value set to $owncloud_url";
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/owncloud.js");
+ }
+
+ function hook_prefs_tab($args) {
+ if ($args != "prefPrefs") return;
+
+ print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Owncloud")."\">";
+
+ print "<br/>";
+
+ $value = $this->host->get($this, "owncloud");
+ print "<form dojoType=\"dijit.form.Form\">";
+
+ print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
+ evt.preventDefault();
+ if (this.validate()) {
+ console.log(dojo.objectToQuery(this.getValues()));
+ new Ajax.Request('backend.php', {
+ parameters: dojo.objectToQuery(this.getValues()),
+ onComplete: function(transport) {
+ notify_info(transport.responseText);
+ }
+ });
+ }
+ </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=\"owncloud\">";
+ print "<table width=\"100%\" class=\"prefPrefsList\">";
+ print "<tr><td width=\"40%\">".__("Owncloud url")."</td>";
+ print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"owncloud_url\" regExp='^(http|https)://.*' value=\"$value\"></td></tr>";
+ print "</table>";
+ print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".__("Save")."</button>";
+
+ print "</form>";
+
+ print "</div>"; #pane
+
+ }
+
+ function hook_article_button($line) {
+ return "<img src=\"".theme_image($this->link, "plugins/owncloud/owncloud.png")."\"
+ style=\"cursor : pointer\" style=\"cursor : pointer\"
+ onclick=\"ownArticle(".$line["id"].")\"
+ class='tagsPic' title='".__('Bookmark on OwnCloud ')."'>";
+ }
+
+ function getOwnCloud() {
+ $id = db_escape_string($_REQUEST['id']);
+
+ $result = db_query($this->link, "SELECT title, link
+ FROM ttrss_entries, ttrss_user_entries
+ WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
+
+ if (db_num_rows($result) != 0) {
+ $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
+ 100, '...');
+ $article_link = db_fetch_result($result, 0, 'link');
+ }
+
+ $own_url = $this->host->get($this, "owncloud");
+
+ print json_encode(array("title" => $title, "link" => $article_link,
+ "id" => $id, "ownurl" => $own_url));
+ }
+}
+?>
+++ /dev/null
-<?php
-require_once "config.php";
-
-class OwnCloud extends Plugin {
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Adds support for OwnCloud ReadLater",
- "cy8aer");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- $host->add_hook($host::HOOK_PREFS_TAB, $this);
- }
-
- function save() {
- $owncloud_url = db_escape_string($_POST["owncloud_url"]);
- $this->host->set($this, "owncloud", $owncloud_url);
- echo "Value set to $owncloud_url";
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/owncloud.js");
- }
-
- function hook_prefs_tab($args) {
- if ($args != "prefPrefs") return;
-
- print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Owncloud")."\">";
-
- print "<br/>";
-
- $value = $this->host->get($this, "owncloud");
- print "<form dojoType=\"dijit.form.Form\">";
-
- print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
- evt.preventDefault();
- if (this.validate()) {
- console.log(dojo.objectToQuery(this.getValues()));
- new Ajax.Request('backend.php', {
- parameters: dojo.objectToQuery(this.getValues()),
- onComplete: function(transport) {
- notify_info(transport.responseText);
- }
- });
- }
- </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=\"owncloud\">";
- print "<table width=\"100%\" class=\"prefPrefsList\">";
- print "<tr><td width=\"40%\">".__("Owncloud url")."</td>";
- print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"owncloud_url\" regExp='^(http|https)://.*' value=\"$value\"></td></tr>";
- print "</table>";
- print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".__("Save")."</button>";
-
- print "</form>";
-
- print "</div>"; #pane
-
- }
-
- function hook_article_button($line) {
- return "<img src=\"".theme_image($this->link, "plugins/owncloud/owncloud.png")."\"
- style=\"cursor : pointer\" style=\"cursor : pointer\"
- onclick=\"ownArticle(".$line["id"].")\"
- class='tagsPic' title='".__('Bookmark on OwnCloud ')."'>";
- }
-
- function getOwnCloud() {
- $id = db_escape_string($_REQUEST['id']);
-
- $result = db_query($this->link, "SELECT title, link
- FROM ttrss_entries, ttrss_user_entries
- WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
-
- if (db_num_rows($result) != 0) {
- $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
- 100, '...');
- $article_link = db_fetch_result($result, 0, 'link');
- }
-
- $own_url = $this->host->get($this, "owncloud");
-
- print json_encode(array("title" => $title, "link" => $article_link,
- "id" => $id, "ownurl" => $own_url));
- }
-}
-?>
--- /dev/null
+<?php
+class Pinterest extends Plugin {
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Share article on Pinterest",
+ "?");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/pinterest.js");
+ }
+
+ function hook_article_button($line) {
+ $article_id = $line["id"];
+
+ $rv = "<img src=\"".theme_image($this->link, 'plugins/pinterest/pinterest.png')."\"
+ class='tagsPic' style=\"cursor : pointer\"
+ onclick=\"pinterest($article_id)\"
+ title='".__('Pinterest')."'>";
+
+ return $rv;
+ }
+
+ function getInfo() {
+ $id = db_escape_string($_REQUEST['id']);
+
+ $result = db_query($this->link, "SELECT title, link
+ FROM ttrss_entries, ttrss_user_entries
+ WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
+
+ if (db_num_rows($result) != 0) {
+ $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
+ 100, '...');
+ $article_link = db_fetch_result($result, 0, 'link');
+ }
+
+ print json_encode(array("title" => $title, "link" => $article_link,
+ "id" => $id));
+ }
+
+
+}
+?>
+++ /dev/null
-<?php
-class Pinterest extends Plugin {
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Share article on Pinterest",
- "?");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/pinterest.js");
- }
-
- function hook_article_button($line) {
- $article_id = $line["id"];
-
- $rv = "<img src=\"".theme_image($this->link, 'plugins/pinterest/pinterest.png')."\"
- class='tagsPic' style=\"cursor : pointer\"
- onclick=\"pinterest($article_id)\"
- title='".__('Pinterest')."'>";
-
- return $rv;
- }
-
- function getInfo() {
- $id = db_escape_string($_REQUEST['id']);
-
- $result = db_query($this->link, "SELECT title, link
- FROM ttrss_entries, ttrss_user_entries
- WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
-
- if (db_num_rows($result) != 0) {
- $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
- 100, '...');
- $article_link = db_fetch_result($result, 0, 'link');
- }
-
- print json_encode(array("title" => $title, "link" => $article_link,
- "id" => $id));
- }
-
-
-}
-?>
--- /dev/null
+<?php
+class Pocket extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Share article on Pocket (formerly Read It Later)",
+ "?");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/pocket.js");
+ }
+
+ function hook_article_button($line) {
+ $article_id = $line["id"];
+
+ $rv = "<img src=\"".theme_image($this->link, 'plugins/pocket/pocket.png')."\"
+ class='tagsPic' style=\"cursor : pointer\"
+ onclick=\"shareArticleToPocket($article_id)\"
+ title='".__('Pocket')."'>";
+
+ return $rv;
+ }
+
+ function getInfo() {
+ $id = db_escape_string($_REQUEST['id']);
+
+ $result = db_query($this->link, "SELECT title, link
+ FROM ttrss_entries, ttrss_user_entries
+ WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
+
+ if (db_num_rows($result) != 0) {
+ $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
+ 100, '...');
+ $article_link = db_fetch_result($result, 0, 'link');
+ }
+
+ print json_encode(array("title" => $title, "link" => $article_link,
+ "id" => $id));
+ }
+
+
+}
+?>
+++ /dev/null
-<?php
-class Pocket extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Share article on Pocket (formerly Read It Later)",
- "?");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/pocket.js");
- }
-
- function hook_article_button($line) {
- $article_id = $line["id"];
-
- $rv = "<img src=\"".theme_image($this->link, 'plugins/pocket/pocket.png')."\"
- class='tagsPic' style=\"cursor : pointer\"
- onclick=\"shareArticleToPocket($article_id)\"
- title='".__('Pocket')."'>";
-
- return $rv;
- }
-
- function getInfo() {
- $id = db_escape_string($_REQUEST['id']);
-
- $result = db_query($this->link, "SELECT title, link
- FROM ttrss_entries, ttrss_user_entries
- WHERE id = '$id' AND ref_id = id AND owner_uid = " .$_SESSION['uid']);
-
- if (db_num_rows($result) != 0) {
- $title = truncate_string(strip_tags(db_fetch_result($result, 0, 'title')),
- 100, '...');
- $article_link = db_fetch_result($result, 0, 'link');
- }
-
- print json_encode(array("title" => $title, "link" => $article_link,
- "id" => $id));
- }
-
-
-}
-?>
--- /dev/null
+<?php
+class Share extends Plugin {
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Share article by unique URL",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
+ }
+
+ function get_js() {
+ return file_get_contents(dirname(__FILE__) . "/share.js");
+ }
+
+ function hook_article_button($line) {
+ return "<img src=\"".theme_image($this->link, 'plugins/share/share.png')."\"
+ class='tagsPic' style=\"cursor : pointer\"
+ onclick=\"shareArticle(".$line['int_id'].")\"
+ title='".__('Share by URL')."'>";
+ }
+
+ 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'
+ AND 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'
+ AND 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>";
+ }
+
+
+}
+?>
+++ /dev/null
-<?php
-class Share extends Plugin {
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Share article by unique URL",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this);
- }
-
- function get_js() {
- return file_get_contents(dirname(__FILE__) . "/share.js");
- }
-
- function hook_article_button($line) {
- return "<img src=\"".theme_image($this->link, 'plugins/share/share.png')."\"
- class='tagsPic' style=\"cursor : pointer\"
- onclick=\"shareArticle(".$line['int_id'].")\"
- title='".__('Share by URL')."'>";
- }
-
- 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'
- AND 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'
- AND 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>";
- }
-
-
-}
-?>
--- /dev/null
+<?php
+class Swap_JK extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Swap j and k hotkeys (for vi brethren)",
+ "fox");
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_HOTKEY_MAP, $this);
+ }
+
+ function hook_hotkey_map($hotkeys) {
+
+ $hotkeys["j"] = "next_feed";
+ $hotkeys["k"] = "prev_feed";
+
+ return $hotkeys;
+
+ }
+}
+?>
+++ /dev/null
-<?php
-class Swap_JK extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Swap j and k hotkeys (for vi brethren)",
- "fox");
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_HOTKEY_MAP, $this);
- }
-
- function hook_hotkey_map($hotkeys) {
-
- $hotkeys["j"] = "next_feed";
- $hotkeys["k"] = "prev_feed";
-
- return $hotkeys;
-
- }
-}
-?>
--- /dev/null
+<?php
+class Updater extends Plugin {
+
+ private $link;
+ private $host;
+
+ function about() {
+ return array(1.0,
+ "Updates tt-rss installation to latest version.",
+ "fox",
+ true);
+ }
+
+ function init($host) {
+ $this->link = $host->get_link();
+ $this->host = $host;
+
+ $host->add_hook($host::HOOK_PREFS_TAB, $this);
+
+ $host->add_command("update-self",
+ "update tt-rss installation to latest version",
+ $this);
+ }
+
+ function update_self_step($link, $step, $params, $force = false) {
+ // __FILE__ is in plugins/updater so we need to go one level up
+ $work_dir = dirname(dirname(dirname(__FILE__)));
+ $parent_dir = dirname($work_dir);
+
+ if (!chdir($work_dir)) {
+ array_push($log, "Unable to change to work directory: $work_dir");
+ $stop = true; break;
+ }
+
+ $stop = false;
+ $log = array();
+ if (!is_array($params)) $params = array();
+
+ switch ($step) {
+ case 0:
+ array_push($log, "Work directory: $work_dir");
+
+ if (!is_writable($work_dir) && !is_writable("$parent_dir")) {
+ $user = posix_getpwuid(posix_geteuid());
+ $user = $user["name"];
+ array_push($log, "Both tt-rss and parent directories should be writable as current user ($user).");
+ $stop = true; break;
+ }
+
+ if (!file_exists("$work_dir/config.php") || !file_exists("$work_dir/include/sanity_check.php")) {
+ array_push($log, "Work directory $work_dir doesn't look like tt-rss installation.");
+ $stop = true; break;
+ }
+
+ if (!is_writable(sys_get_temp_dir())) {
+ array_push($log, "System temporary directory should be writable as current user.");
+ $stop = true; break;
+ }
+
+ array_push($log, "Checking for tar...");
+
+ $system_rc = 0;
+ system("tar --version >/dev/null", $system_rc);
+
+ if ($system_rc != 0) {
+ array_push($log, "Could not run tar executable (RC=$system_rc).");
+ $stop = true; break;
+ }
+
+ array_push($log, "Checking for gunzip...");
+
+ $system_rc = 0;
+ system("gunzip --version >/dev/null", $system_rc);
+
+ if ($system_rc != 0) {
+ array_push($log, "Could not run gunzip executable (RC=$system_rc).");
+ $stop = true; break;
+ }
+
+
+ array_push($log, "Checking for latest version...");
+
+ $version_info = json_decode(fetch_file_contents("http://tt-rss.org/version.php"),
+ true);
+
+ if (!is_array($version_info)) {
+ array_push($log, "Unable to fetch version information.");
+ $stop = true; break;
+ }
+
+ $target_version = $version_info["version"];
+ $target_dir = "$parent_dir/tt-rss-$target_version";
+
+ array_push($log, "Target version: $target_version");
+ $params["target_version"] = $target_version;
+
+ if (version_compare(VERSION, $target_version) != -1 && !$force) {
+ array_push($log, "Your Tiny Tiny RSS installation is up to date.");
+ $stop = true; break;
+ }
+
+ if (file_exists($target_dir)) {
+ array_push($log, "Target directory $target_dir already exists.");
+ $stop = true; break;
+ }
+
+ break;
+ case 1:
+ $target_version = $params["target_version"];
+
+ array_push($log, "Downloading checksums...");
+ $md5sum_data = fetch_file_contents("http://tt-rss.org/download/md5sum.txt");
+
+ if (!$md5sum_data) {
+ array_push($log, "Could not download checksums.");
+ $stop = true; break;
+ }
+
+ $md5sum_data = explode("\n", $md5sum_data);
+
+ foreach ($md5sum_data as $line) {
+ $pair = explode(" ", $line);
+
+ if ($pair[1] == "tt-rss-$target_version.tar.gz") {
+ $target_md5sum = $pair[0];
+ break;
+ }
+ }
+
+ if (!$target_md5sum) {
+ array_push($log, "Unable to locate checksum for target version.");
+ $stop = true; break;
+ }
+
+ $params["target_md5sum"] = $target_md5sum;
+
+ break;
+ case 2:
+ $target_version = $params["target_version"];
+ $target_md5sum = $params["target_md5sum"];
+
+ array_push($log, "Downloading distribution tarball...");
+
+ $tarball_url = "http://tt-rss.org/download/tt-rss-$target_version.tar.gz";
+ $data = fetch_file_contents($tarball_url);
+
+ if (!$data) {
+ array_push($log, "Could not download distribution tarball ($tarball_url).");
+ $stop = true; break;
+ }
+
+ array_push($log, "Verifying tarball checksum...");
+
+ $test_md5sum = md5($data);
+
+ if ($test_md5sum != $target_md5sum) {
+ array_push($log, "Downloaded checksum doesn't match (got $test_md5sum, expected $target_md5sum).");
+ $stop = true; break;
+ }
+
+ $tmp_file = tempnam(sys_get_temp_dir(), 'tt-rss');
+ array_push($log, "Saving download to $tmp_file");
+
+ if (!file_put_contents($tmp_file, $data)) {
+ array_push($log, "Unable to save download.");
+ $stop = true; break;
+ }
+
+ $params["tmp_file"] = $tmp_file;
+
+ break;
+ case 3:
+ $tmp_file = $params["tmp_file"];
+ $target_version = $params["target_version"];
+
+ if (!chdir($parent_dir)) {
+ array_push($log, "Unable to change into parent directory.");
+ $stop = true; break;
+ }
+
+ $old_dir = tmpdirname($parent_dir, "tt-rss-old");
+
+ array_push($log, "Renaming tt-rss directory to ".basename($old_dir));
+ if (!rename($work_dir, $old_dir)) {
+ array_push($log, "Unable to rename tt-rss directory.");
+ $stop = true; break;
+ }
+
+ array_push($log, "Extracting tarball...");
+ system("tar zxf $tmp_file", $system_rc);
+
+ if ($system_rc != 0) {
+ array_push($log, "Error while extracting tarball (RC=$system_rc).");
+ $stop = true; break;
+ }
+
+ $target_dir = "$parent_dir/tt-rss-$target_version";
+
+ array_push($log, "Renaming target directory...");
+ if (!rename($target_dir, $work_dir)) {
+ array_push($log, "Unable to rename target directory.");
+ $stop = true; break;
+ }
+
+ if (!chdir($work_dir)) {
+ array_push($log, "Unable to change to work directory: $work_dir");
+ $stop = true; break;
+ }
+
+ array_push($log, "Copying config.php...");
+ if (!copy("$old_dir/config.php", "$work_dir/config.php")) {
+ array_push($log, "Unable to copy config.php to $work_dir.");
+ $stop = true; break;
+ }
+
+ array_push($log, "Cleaning up...");
+ unlink($tmp_file);
+
+ array_push($log, "Fixing permissions...");
+
+ $directories = array(
+ CACHE_DIR,
+ CACHE_DIR . "/export",
+ CACHE_DIR . "/images",
+ CACHE_DIR . "/simplepie",
+ ICONS_DIR,
+ LOCK_DIRECTORY);
+
+ foreach ($directories as $dir) {
+ array_push($log, "-> $dir");
+ chmod($dir, 0777);
+ }
+
+ array_push($log, "Upgrade completed.");
+ array_push($log, "Your old tt-rss directory is saved at $old_dir. ".
+ "Please migrate locally modified files (if any) and remove it.");
+ array_push($log, "You might need to re-enter current directory in shell to see new files.");
+
+ $stop = true;
+ break;
+ default:
+ $stop = true;
+ }
+
+ return array("step" => $step, "stop" => $stop, "params" => $params, "log" => $log);
+ }
+
+ function update_self_cli($link, $force = false) {
+ $step = 0;
+ $stop = false;
+ $params = array();
+
+ while (!$stop) {
+ $rc = $this->update_self_step($link, $step, $params, $force);
+
+ $params = $rc['params'];
+ $stop = $rc['stop'];
+
+ foreach ($rc['log'] as $line) {
+ _debug($line);
+ }
+ ++$step;
+ }
+ }
+
+ function update_self($args) {
+ _debug("Warning: self-updating is experimental. Use at your own risk.");
+ _debug("Please backup your tt-rss directory before continuing. Your database will not be modified.");
+ _debug("Type 'yes' to continue.");
+
+ if (read_stdin() != 'yes')
+ exit;
+
+ $this->update_self_cli($link, in_array("-force", $args));
+ }
+
+ function get_prefs_js() {
+ return file_get_contents(dirname(__FILE__) . "/updater.js");
+ }
+
+ function hook_prefs_tab($args) {
+ if ($args != "prefPrefs") return;
+
+ if (($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) && CHECK_FOR_NEW_VERSION) {
+ print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Update Tiny Tiny RSS')."\">";
+
+ if ($_SESSION["pref_last_version_check"] + 86400 + rand(-1000, 1000) < time()) {
+ $_SESSION["version_data"] = @check_for_update($this->link);
+ $_SESSION["pref_last_version_check"] = time();
+ }
+
+ if (is_array($_SESSION["version_data"])) {
+ $version = $_SESSION["version_data"]["version"];
+ print_notice(T_sprintf("New version of Tiny Tiny RSS is available (%s).", "<b>$version</b>"));
+
+ print "<p><button dojoType=\"dijit.form.Button\" onclick=\"return updateSelf()\">".
+ __('Update Tiny Tiny RSS')."</button></p>";
+
+ } else {
+ print_notice(__("Your Tiny Tiny RSS installation is up to date."));
+ }
+
+ print "</div>"; #pane
+ }
+
+ function updateSelf() {
+ print "<form style='display : block' name='self_update_form' id='self_update_form'>";
+
+ print "<div class='error'>".__("Do not close this dialog until updating is finished. Backup your tt-rss directory before continuing.")."</div>";
+
+ print "<ul class='selfUpdateList' id='self_update_log'>";
+ print "<li>" . __("Ready to update.") . "</li>";
+ print "</ul>";
+
+ print "<div class='dlgButtons'>";
+ print "<button id=\"self_update_start_btn\" dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('updateSelfDlg').start()\" >".
+ __("Start update")."</button>";
+ print "<button id=\"self_update_stop_btn\" onclick=\"return dijit.byId('updateSelfDlg').close()\" dojoType=\"dijit.form.Button\">".
+ __("Close this window")."</button>";
+ print "</div>";
+ print "</form>";
+ }
+
+ function performUpdate() {
+ $step = (int) $_REQUEST["step"];
+ $params = json_decode($_REQUEST["params"], true);
+ $force = (bool) $_REQUEST["force"];
+
+ if (($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) && CHECK_FOR_NEW_VERSION) {
+ print json_encode($this->update_self_step($this->link, $step, $params, $force));
+ }
+ }
+
+
+ }
+}
+?>
+++ /dev/null
-<?php
-class Updater extends Plugin {
-
- private $link;
- private $host;
-
- function about() {
- return array(1.0,
- "Updates tt-rss installation to latest version.",
- "fox",
- true);
- }
-
- function init($host) {
- $this->link = $host->get_link();
- $this->host = $host;
-
- $host->add_hook($host::HOOK_PREFS_TAB, $this);
-
- $host->add_command("update-self",
- "update tt-rss installation to latest version",
- $this);
- }
-
- function update_self_step($link, $step, $params, $force = false) {
- // __FILE__ is in plugins/updater so we need to go one level up
- $work_dir = dirname(dirname(dirname(__FILE__)));
- $parent_dir = dirname($work_dir);
-
- if (!chdir($work_dir)) {
- array_push($log, "Unable to change to work directory: $work_dir");
- $stop = true; break;
- }
-
- $stop = false;
- $log = array();
- if (!is_array($params)) $params = array();
-
- switch ($step) {
- case 0:
- array_push($log, "Work directory: $work_dir");
-
- if (!is_writable($work_dir) && !is_writable("$parent_dir")) {
- $user = posix_getpwuid(posix_geteuid());
- $user = $user["name"];
- array_push($log, "Both tt-rss and parent directories should be writable as current user ($user).");
- $stop = true; break;
- }
-
- if (!file_exists("$work_dir/config.php") || !file_exists("$work_dir/include/sanity_check.php")) {
- array_push($log, "Work directory $work_dir doesn't look like tt-rss installation.");
- $stop = true; break;
- }
-
- if (!is_writable(sys_get_temp_dir())) {
- array_push($log, "System temporary directory should be writable as current user.");
- $stop = true; break;
- }
-
- array_push($log, "Checking for tar...");
-
- $system_rc = 0;
- system("tar --version >/dev/null", $system_rc);
-
- if ($system_rc != 0) {
- array_push($log, "Could not run tar executable (RC=$system_rc).");
- $stop = true; break;
- }
-
- array_push($log, "Checking for gunzip...");
-
- $system_rc = 0;
- system("gunzip --version >/dev/null", $system_rc);
-
- if ($system_rc != 0) {
- array_push($log, "Could not run gunzip executable (RC=$system_rc).");
- $stop = true; break;
- }
-
-
- array_push($log, "Checking for latest version...");
-
- $version_info = json_decode(fetch_file_contents("http://tt-rss.org/version.php"),
- true);
-
- if (!is_array($version_info)) {
- array_push($log, "Unable to fetch version information.");
- $stop = true; break;
- }
-
- $target_version = $version_info["version"];
- $target_dir = "$parent_dir/tt-rss-$target_version";
-
- array_push($log, "Target version: $target_version");
- $params["target_version"] = $target_version;
-
- if (version_compare(VERSION, $target_version) != -1 && !$force) {
- array_push($log, "Your Tiny Tiny RSS installation is up to date.");
- $stop = true; break;
- }
-
- if (file_exists($target_dir)) {
- array_push($log, "Target directory $target_dir already exists.");
- $stop = true; break;
- }
-
- break;
- case 1:
- $target_version = $params["target_version"];
-
- array_push($log, "Downloading checksums...");
- $md5sum_data = fetch_file_contents("http://tt-rss.org/download/md5sum.txt");
-
- if (!$md5sum_data) {
- array_push($log, "Could not download checksums.");
- $stop = true; break;
- }
-
- $md5sum_data = explode("\n", $md5sum_data);
-
- foreach ($md5sum_data as $line) {
- $pair = explode(" ", $line);
-
- if ($pair[1] == "tt-rss-$target_version.tar.gz") {
- $target_md5sum = $pair[0];
- break;
- }
- }
-
- if (!$target_md5sum) {
- array_push($log, "Unable to locate checksum for target version.");
- $stop = true; break;
- }
-
- $params["target_md5sum"] = $target_md5sum;
-
- break;
- case 2:
- $target_version = $params["target_version"];
- $target_md5sum = $params["target_md5sum"];
-
- array_push($log, "Downloading distribution tarball...");
-
- $tarball_url = "http://tt-rss.org/download/tt-rss-$target_version.tar.gz";
- $data = fetch_file_contents($tarball_url);
-
- if (!$data) {
- array_push($log, "Could not download distribution tarball ($tarball_url).");
- $stop = true; break;
- }
-
- array_push($log, "Verifying tarball checksum...");
-
- $test_md5sum = md5($data);
-
- if ($test_md5sum != $target_md5sum) {
- array_push($log, "Downloaded checksum doesn't match (got $test_md5sum, expected $target_md5sum).");
- $stop = true; break;
- }
-
- $tmp_file = tempnam(sys_get_temp_dir(), 'tt-rss');
- array_push($log, "Saving download to $tmp_file");
-
- if (!file_put_contents($tmp_file, $data)) {
- array_push($log, "Unable to save download.");
- $stop = true; break;
- }
-
- $params["tmp_file"] = $tmp_file;
-
- break;
- case 3:
- $tmp_file = $params["tmp_file"];
- $target_version = $params["target_version"];
-
- if (!chdir($parent_dir)) {
- array_push($log, "Unable to change into parent directory.");
- $stop = true; break;
- }
-
- $old_dir = tmpdirname($parent_dir, "tt-rss-old");
-
- array_push($log, "Renaming tt-rss directory to ".basename($old_dir));
- if (!rename($work_dir, $old_dir)) {
- array_push($log, "Unable to rename tt-rss directory.");
- $stop = true; break;
- }
-
- array_push($log, "Extracting tarball...");
- system("tar zxf $tmp_file", $system_rc);
-
- if ($system_rc != 0) {
- array_push($log, "Error while extracting tarball (RC=$system_rc).");
- $stop = true; break;
- }
-
- $target_dir = "$parent_dir/tt-rss-$target_version";
-
- array_push($log, "Renaming target directory...");
- if (!rename($target_dir, $work_dir)) {
- array_push($log, "Unable to rename target directory.");
- $stop = true; break;
- }
-
- if (!chdir($work_dir)) {
- array_push($log, "Unable to change to work directory: $work_dir");
- $stop = true; break;
- }
-
- array_push($log, "Copying config.php...");
- if (!copy("$old_dir/config.php", "$work_dir/config.php")) {
- array_push($log, "Unable to copy config.php to $work_dir.");
- $stop = true; break;
- }
-
- array_push($log, "Cleaning up...");
- unlink($tmp_file);
-
- array_push($log, "Fixing permissions...");
-
- $directories = array(
- CACHE_DIR,
- CACHE_DIR . "/export",
- CACHE_DIR . "/images",
- CACHE_DIR . "/simplepie",
- ICONS_DIR,
- LOCK_DIRECTORY);
-
- foreach ($directories as $dir) {
- array_push($log, "-> $dir");
- chmod($dir, 0777);
- }
-
- array_push($log, "Upgrade completed.");
- array_push($log, "Your old tt-rss directory is saved at $old_dir. ".
- "Please migrate locally modified files (if any) and remove it.");
- array_push($log, "You might need to re-enter current directory in shell to see new files.");
-
- $stop = true;
- break;
- default:
- $stop = true;
- }
-
- return array("step" => $step, "stop" => $stop, "params" => $params, "log" => $log);
- }
-
- function update_self_cli($link, $force = false) {
- $step = 0;
- $stop = false;
- $params = array();
-
- while (!$stop) {
- $rc = $this->update_self_step($link, $step, $params, $force);
-
- $params = $rc['params'];
- $stop = $rc['stop'];
-
- foreach ($rc['log'] as $line) {
- _debug($line);
- }
- ++$step;
- }
- }
-
- function update_self($args) {
- _debug("Warning: self-updating is experimental. Use at your own risk.");
- _debug("Please backup your tt-rss directory before continuing. Your database will not be modified.");
- _debug("Type 'yes' to continue.");
-
- if (read_stdin() != 'yes')
- exit;
-
- $this->update_self_cli($link, in_array("-force", $args));
- }
-
- function get_prefs_js() {
- return file_get_contents(dirname(__FILE__) . "/updater.js");
- }
-
- function hook_prefs_tab($args) {
- if ($args != "prefPrefs") return;
-
- if (($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) && CHECK_FOR_NEW_VERSION) {
- print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Update Tiny Tiny RSS')."\">";
-
- if ($_SESSION["pref_last_version_check"] + 86400 + rand(-1000, 1000) < time()) {
- $_SESSION["version_data"] = @check_for_update($this->link);
- $_SESSION["pref_last_version_check"] = time();
- }
-
- if (is_array($_SESSION["version_data"])) {
- $version = $_SESSION["version_data"]["version"];
- print_notice(T_sprintf("New version of Tiny Tiny RSS is available (%s).", "<b>$version</b>"));
-
- print "<p><button dojoType=\"dijit.form.Button\" onclick=\"return updateSelf()\">".
- __('Update Tiny Tiny RSS')."</button></p>";
-
- } else {
- print_notice(__("Your Tiny Tiny RSS installation is up to date."));
- }
-
- print "</div>"; #pane
- }
-
- function updateSelf() {
- print "<form style='display : block' name='self_update_form' id='self_update_form'>";
-
- print "<div class='error'>".__("Do not close this dialog until updating is finished. Backup your tt-rss directory before continuing.")."</div>";
-
- print "<ul class='selfUpdateList' id='self_update_log'>";
- print "<li>" . __("Ready to update.") . "</li>";
- print "</ul>";
-
- print "<div class='dlgButtons'>";
- print "<button id=\"self_update_start_btn\" dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('updateSelfDlg').start()\" >".
- __("Start update")."</button>";
- print "<button id=\"self_update_stop_btn\" onclick=\"return dijit.byId('updateSelfDlg').close()\" dojoType=\"dijit.form.Button\">".
- __("Close this window")."</button>";
- print "</div>";
- print "</form>";
- }
-
- function performUpdate() {
- $step = (int) $_REQUEST["step"];
- $params = json_decode($_REQUEST["params"], true);
- $force = (bool) $_REQUEST["force"];
-
- if (($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) && CHECK_FOR_NEW_VERSION) {
- print json_encode($this->update_self_step($this->link, $step, $params, $force));
- }
- }
-
-
- }
-}
-?>