]> git.wh0rd.org Git - tt-rss.git/commitdiff
rework class system to use subdirectories
authorAndrew Dolgov <fox@madoka.volgo-balt.ru>
Fri, 17 Aug 2012 10:20:55 +0000 (14:20 +0400)
committerAndrew Dolgov <fox@madoka.volgo-balt.ru>
Fri, 17 Aug 2012 10:22:33 +0000 (14:22 +0400)
add placeholder plugin/hook system

45 files changed:
backend.php
classes/article.php
classes/auth/base.php [new file with mode: 0644]
classes/auth/internal.php [new file with mode: 0644]
classes/auth/remote.php [new file with mode: 0644]
classes/auth_base.php [deleted file]
classes/auth_internal.php [deleted file]
classes/auth_remote.php [deleted file]
classes/button.php [new file with mode: 0644]
classes/button/mail.php [new file with mode: 0644]
classes/button/note.php [new file with mode: 0644]
classes/button/share.php [new file with mode: 0644]
classes/button/tweet.php [new file with mode: 0644]
classes/feeds.php
classes/handler/protected.php [new file with mode: 0644]
classes/handler/public.php [new file with mode: 0644]
classes/mail_button.php [deleted file]
classes/note_button.php [deleted file]
classes/opml.php
classes/plugin.php [new file with mode: 0644]
classes/plugin/example.php [new file with mode: 0644]
classes/plugin_button.php [deleted file]
classes/plugins.php [new file with mode: 0644]
classes/pref/feeds.php [new file with mode: 0644]
classes/pref/filters.php [new file with mode: 0644]
classes/pref/instances.php [new file with mode: 0644]
classes/pref/labels.php [new file with mode: 0644]
classes/pref/prefs.php [new file with mode: 0644]
classes/pref/users.php [new file with mode: 0644]
classes/pref_feeds.php [deleted file]
classes/pref_filters.php [deleted file]
classes/pref_instances.php [deleted file]
classes/pref_labels.php [deleted file]
classes/pref_prefs.php [deleted file]
classes/pref_users.php [deleted file]
classes/protected_handler.php [deleted file]
classes/public_handler.php [deleted file]
classes/rpc.php
classes/share_button.php [deleted file]
classes/tweet_button.php [deleted file]
include/functions.php
include/rssfuncs.php
public.php
update.php
update_daemon2.php

index 13568d1657d605277362672a7d6fe6fcac7f1049..b0ef5e0f1f2db261b54faa052a52874850c3dd95 100644 (file)
@@ -77,6 +77,8 @@
                return;
        }
 
+       $plugins = new Plugins($link);
+
        $purge_intervals = array(
                0  => __("Use default"),
                -1 => __("Never purge"),
index 30f0c7d10391b69e88bcd8f6b3a60d712f2cea6e..16619c9ad02ec2cc1ad28c12657a99f63e59deca 100644 (file)
@@ -1,5 +1,5 @@
 <?php\r
-class Article extends Protected_Handler {\r
+class Article extends Handler_Protected {\r
 \r
        function csrf_ignore($method) {\r
                $csrf_ignored = array("redirect");\r
diff --git a/classes/auth/base.php b/classes/auth/base.php
new file mode 100644 (file)
index 0000000..7c37967
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+class Auth_Base {
+       protected $link;
+
+       function __construct($link) {
+               $this->link = $link;
+       }
+
+       function authenticate($login, $password) {
+               return false;
+       }
+
+       // Auto-creates specified user if allowed by system configuration
+       // Can be used instead of find_user_by_login() by external auth modules
+       function auto_create_user($login) {
+               if ($login && defined('AUTH_AUTO_CREATE') && AUTH_AUTO_CREATE) {
+                       $user_id = $this->find_user_by_login($login);
+
+                       if (!$user_id) {
+                               $login = db_escape_string($login);
+                               $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
+                               $pwd_hash = encrypt_password($password, $salt, true);
+
+                               $query = "INSERT INTO ttrss_users
+                                               (login,access_level,last_login,created,pwd_hash,salt)
+                                               VALUES ('$login', 0, null, NOW(), '$pwd_hash','$salt')";
+
+                               db_query($this->link, $query);
+
+                               return $this->find_user_by_login($login);
+
+                       } else {
+                               return $user_id;
+                       }
+               }
+
+               return $this->find_user_by_login($login);
+       }
+
+       function find_user_by_login($login) {
+               $login = db_escape_string($login);
+
+               $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
+                       login = '$login'");
+
+               if (db_num_rows($result) > 0) {
+                       return db_fetch_result($result, 0, "id");
+               } else {
+                       return false;
+               }
+
+       }
+}
+
+?>
diff --git a/classes/auth/internal.php b/classes/auth/internal.php
new file mode 100644 (file)
index 0000000..8890d44
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+class Auth_Internal extends Auth_Base {
+
+       function authenticate($login, $password) {
+
+               $pwd_hash1 = encrypt_password($password);
+               $pwd_hash2 = encrypt_password($password, $login);
+               $login = db_escape_string($login);
+
+               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 change_password($owner_uid, $old_password, $new_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) {
+                       $old_password_hash1 = encrypt_password($old_password);
+                       $old_password_hash2 = encrypt_password($old_password, $login);
+
+                       $query = "SELECT id FROM ttrss_users WHERE
+                               id = '$owner_uid' AND (pwd_hash = '$old_password_hash1' OR
+                               pwd_hash = '$old_password_hash2')";
+
+               } else {
+                       $old_password_hash = encrypt_password($old_password, $salt, true);
+
+                       $query = "SELECT id FROM ttrss_users WHERE
+                               id = '$owner_uid' AND pwd_hash = '$old_password_hash'";
+               }
+
+               $result = db_query($this->link, $query);
+
+               if (db_num_rows($result) == 1) {
+
+                       $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'
+                                       WHERE id = '$owner_uid'");
+
+                       $_SESSION["pwd_hash"] = $new_password_hash;
+
+                       return __("Password has been changed.");
+               } else {
+                       return "ERROR: ".__('Old password is incorrect.');
+               }
+       }
+}
+?>
diff --git a/classes/auth/remote.php b/classes/auth/remote.php
new file mode 100644 (file)
index 0000000..6892a35
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+class Auth_Remote extends Auth_Base {
+       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->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;
+       }
+}
+
+?>
diff --git a/classes/auth_base.php b/classes/auth_base.php
deleted file mode 100644 (file)
index 7c37967..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-class Auth_Base {
-       protected $link;
-
-       function __construct($link) {
-               $this->link = $link;
-       }
-
-       function authenticate($login, $password) {
-               return false;
-       }
-
-       // Auto-creates specified user if allowed by system configuration
-       // Can be used instead of find_user_by_login() by external auth modules
-       function auto_create_user($login) {
-               if ($login && defined('AUTH_AUTO_CREATE') && AUTH_AUTO_CREATE) {
-                       $user_id = $this->find_user_by_login($login);
-
-                       if (!$user_id) {
-                               $login = db_escape_string($login);
-                               $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
-                               $pwd_hash = encrypt_password($password, $salt, true);
-
-                               $query = "INSERT INTO ttrss_users
-                                               (login,access_level,last_login,created,pwd_hash,salt)
-                                               VALUES ('$login', 0, null, NOW(), '$pwd_hash','$salt')";
-
-                               db_query($this->link, $query);
-
-                               return $this->find_user_by_login($login);
-
-                       } else {
-                               return $user_id;
-                       }
-               }
-
-               return $this->find_user_by_login($login);
-       }
-
-       function find_user_by_login($login) {
-               $login = db_escape_string($login);
-
-               $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
-                       login = '$login'");
-
-               if (db_num_rows($result) > 0) {
-                       return db_fetch_result($result, 0, "id");
-               } else {
-                       return false;
-               }
-
-       }
-}
-
-?>
diff --git a/classes/auth_internal.php b/classes/auth_internal.php
deleted file mode 100644 (file)
index 8890d44..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-<?php
-class Auth_Internal extends Auth_Base {
-
-       function authenticate($login, $password) {
-
-               $pwd_hash1 = encrypt_password($password);
-               $pwd_hash2 = encrypt_password($password, $login);
-               $login = db_escape_string($login);
-
-               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 change_password($owner_uid, $old_password, $new_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) {
-                       $old_password_hash1 = encrypt_password($old_password);
-                       $old_password_hash2 = encrypt_password($old_password, $login);
-
-                       $query = "SELECT id FROM ttrss_users WHERE
-                               id = '$owner_uid' AND (pwd_hash = '$old_password_hash1' OR
-                               pwd_hash = '$old_password_hash2')";
-
-               } else {
-                       $old_password_hash = encrypt_password($old_password, $salt, true);
-
-                       $query = "SELECT id FROM ttrss_users WHERE
-                               id = '$owner_uid' AND pwd_hash = '$old_password_hash'";
-               }
-
-               $result = db_query($this->link, $query);
-
-               if (db_num_rows($result) == 1) {
-
-                       $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'
-                                       WHERE id = '$owner_uid'");
-
-                       $_SESSION["pwd_hash"] = $new_password_hash;
-
-                       return __("Password has been changed.");
-               } else {
-                       return "ERROR: ".__('Old password is incorrect.');
-               }
-       }
-}
-?>
diff --git a/classes/auth_remote.php b/classes/auth_remote.php
deleted file mode 100644 (file)
index 6892a35..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-class Auth_Remote extends Auth_Base {
-       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->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;
-       }
-}
-
-?>
diff --git a/classes/button.php b/classes/button.php
new file mode 100644 (file)
index 0000000..24d576d
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+class Button {
+
+       protected $link;
+
+       function __construct($link) {
+               $this->link = $link;
+       }
+
+}
+?>
diff --git a/classes/button/mail.php b/classes/button/mail.php
new file mode 100644 (file)
index 0000000..309493b
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+class Button_Mail extends Button {
+       function render($article_id) {
+               return "<img src=\"".theme_image($link, 'images/art-email.png')."\"
+                                       class='tagsPic' style=\"cursor : pointer\"
+                                       onclick=\"emailArticle($article_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=\"rpc\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"buttonPlugin\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"mail\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin_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>";
+       }
+
+
+}
+?>
diff --git a/classes/button/note.php b/classes/button/note.php
new file mode 100644 (file)
index 0000000..d5b6e38
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+class Button_Note extends Button {
+       function render($article_id) {
+               return "<img src=\"".theme_image($this->link, "images/art-pub-note.png")."\"
+                               style=\"cursor : pointer\" style=\"cursor : pointer\"
+                               onclick=\"editArticleNote($article_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=\"rpc\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"buttonPlugin\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"note\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin_method\" value=\"setNote\">";
+
+               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)));
+       }
+
+
+}
+?>
diff --git a/classes/button/share.php b/classes/button/share.php
new file mode 100644 (file)
index 0000000..74d7128
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+class Button_Share extends Button {
+       function render($article_id, $line) {
+               return "<img src=\"".theme_image($this->link, 'images/art-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>";
+       }
+
+
+}
+?>
diff --git a/classes/button/tweet.php b/classes/button/tweet.php
new file mode 100644 (file)
index 0000000..3157fb7
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+class Button_Tweet extends Button {
+       function render($article_id) {
+               $rv = "<img src=\"".theme_image($this->link, 'images/art-tweet.png')."\"
+                       class='tagsPic' style=\"cursor : pointer\"
+                       onclick=\"tweetArticle($article_id)\"
+                       title='".__('Share on Twitter')."'>";
+
+               return $rv;
+       }
+
+       function getTweetInfo() {
+               $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));
+       }
+
+
+}
+?>
index a3062565a5e227beff4ff94068fe25d9a125869e..7598b0af80061ddbc19c7532bdba0572ffe7939c 100644 (file)
@@ -1,5 +1,5 @@
 <?php\r
-class Feeds extends Protected_Handler {\r
+class Feeds extends Handler_Protected {\r
 \r
        function csrf_ignore($method) {\r
                $csrf_ignored = array("index");\r
@@ -121,6 +121,8 @@ class Feeds extends Protected_Handler {
                                        $next_unread_feed, $offset, $vgr_last_feed = false,\r
                                        $override_order = false, $include_children = false) {\r
 \r
+               global $plugins;\r
+\r
                $disable_cache = false;\r
 \r
                $reply = array();\r
@@ -220,10 +222,12 @@ class Feeds extends Protected_Handler {
 \r
                $headlines_count = db_num_rows($result);\r
 \r
+               $plugins->hook('headlines_before', $reply);\r
+\r
                if (get_pref($this->link, 'COMBINED_DISPLAY_MODE')) {\r
                        $button_plugins = array();\r
                        foreach (explode(",", ARTICLE_BUTTON_PLUGINS) as $p) {\r
-                               $pclass = trim("${p}_button");\r
+                               $pclass = trim("button_${p}");\r
 \r
                                if (class_exists($pclass)) {\r
                                        $plugin = new $pclass($link);\r
@@ -245,6 +249,12 @@ class Feeds extends Protected_Handler {
 \r
                        while ($line = db_fetch_assoc($result)) {\r
 \r
+                               if (get_pref($this->link, 'COMBINED_DISPLAY_MODE')) {\r
+                                       $plugins->hook('cdm_article_before', $line);\r
+                               } else {\r
+                                       $plugins->hook('headlines_row', $line);\r
+                               }\r
+\r
                                $class = ($lnum % 2) ? "even" : "odd";\r
 \r
                                $id = $line["id"];\r
@@ -673,11 +683,15 @@ class Feeds extends Protected_Handler {
 \r
                                        $reply['content'] .= "</div>";\r
 \r
+                                       $plugins->hook('cdm_article_after', $reply['content']);\r
+\r
                                }\r
 \r
                                ++$lnum;\r
                        }\r
 \r
+                       $plugins->hook('headlines_after', $reply);\r
+\r
                        if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PE", $timing_info);\r
 \r
                } else {\r
diff --git a/classes/handler/protected.php b/classes/handler/protected.php
new file mode 100644 (file)
index 0000000..4ce8653
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+class Handler_Protected extends Handler {
+
+       function before($method) {
+               return parent::before($method) && $_SESSION['uid'];
+       }
+}
+?>
diff --git a/classes/handler/public.php b/classes/handler/public.php
new file mode 100644 (file)
index 0000000..983f0aa
--- /dev/null
@@ -0,0 +1,310 @@
+<?php
+class Handler_Public extends Handler {
+
+       private function generate_syndicated_feed($owner_uid, $feed, $is_cat,
+               $limit, $search, $search_mode, $match_on, $view_mode = false) {
+
+               require_once "lib/MiniTemplator.class.php";
+
+               $note_style =   "background-color : #fff7d5;
+                       border-width : 1px; ".
+                       "padding : 5px; border-style : dashed; border-color : #e7d796;".
+                       "margin-bottom : 1em; color : #9a8c59;";
+
+               if (!$limit) $limit = 30;
+
+               if (get_pref($this->link, "SORT_HEADLINES_BY_FEED_DATE", $owner_uid)) {
+                       $date_sort_field = "updated";
+               } else {
+                       $date_sort_field = "date_entered";
+               }
+
+               $qfh_ret = queryFeedHeadlines($this->link, $feed,
+                       $limit, $view_mode, $is_cat, $search, $search_mode,
+                       $match_on, "$date_sort_field DESC", 0, $owner_uid);
+
+               $result = $qfh_ret[0];
+               $feed_title = htmlspecialchars($qfh_ret[1]);
+               $feed_site_url = $qfh_ret[2];
+               $last_error = $qfh_ret[3];
+
+               $feed_self_url = get_self_url_prefix() .
+                       "/public.php?op=rss&id=-2&key=" .
+                       get_feed_access_key($this->link, -2, false, $owner_uid);
+
+               if (!$feed_site_url) $feed_site_url = get_self_url_prefix();
+
+               $tpl = new MiniTemplator;
+
+               $tpl->readTemplateFromFile("templates/generated_feed.txt");
+
+               $tpl->setVariable('FEED_TITLE', $feed_title, true);
+               $tpl->setVariable('VERSION', VERSION, true);
+               $tpl->setVariable('FEED_URL', htmlspecialchars($feed_self_url), true);
+
+               if (PUBSUBHUBBUB_HUB && $feed == -2) {
+                       $tpl->setVariable('HUB_URL', htmlspecialchars(PUBSUBHUBBUB_HUB), true);
+                       $tpl->addBlock('feed_hub');
+               }
+
+               $tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
+
+               while ($line = db_fetch_assoc($result)) {
+                       $tpl->setVariable('ARTICLE_ID', htmlspecialchars($line['link']), true);
+                       $tpl->setVariable('ARTICLE_LINK', htmlspecialchars($line['link']), true);
+                       $tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
+                       $tpl->setVariable('ARTICLE_EXCERPT',
+                               truncate_string(strip_tags($line["content_preview"]), 100, '...'), true);
+
+                       $content = sanitize($this->link, $line["content_preview"], false, $owner_uid);
+
+                       if ($line['note']) {
+                               $content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
+                                       $content;
+                       }
+
+                       $tpl->setVariable('ARTICLE_CONTENT', $content, true);
+
+                       $tpl->setVariable('ARTICLE_UPDATED_ATOM',
+                               date('c', strtotime($line["updated"])), true);
+                       $tpl->setVariable('ARTICLE_UPDATED_RFC822',
+                               date(DATE_RFC822, strtotime($line["updated"])), true);
+
+                       $tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
+
+                       $tags = get_article_tags($this->link, $line["id"], $owner_uid);
+
+                       foreach ($tags as $tag) {
+                               $tpl->setVariable('ARTICLE_CATEGORY', htmlspecialchars($tag), true);
+                               $tpl->addBlock('category');
+                       }
+
+                       $enclosures = get_article_enclosures($this->link, $line["id"]);
+
+                       foreach ($enclosures as $e) {
+                               $type = htmlspecialchars($e['content_type']);
+                               $url = htmlspecialchars($e['content_url']);
+                               $length = $e['duration'];
+
+                               $tpl->setVariable('ARTICLE_ENCLOSURE_URL', $url, true);
+                               $tpl->setVariable('ARTICLE_ENCLOSURE_TYPE', $type, true);
+                               $tpl->setVariable('ARTICLE_ENCLOSURE_LENGTH', $length, true);
+
+                               $tpl->addBlock('enclosure');
+                       }
+
+                       $tpl->addBlock('entry');
+               }
+
+               $tmp = "";
+
+               $tpl->addBlock('feed');
+               $tpl->generateOutputToString($tmp);
+
+               print $tmp;
+       }
+
+       function getUnread() {
+               $login = db_escape_string($_REQUEST["login"]);
+               $fresh = $_REQUEST["fresh"] == "1";
+
+               $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE login = '$login'");
+
+               if (db_num_rows($result) == 1) {
+                       $uid = db_fetch_result($result, 0, "id");
+
+                       print getGlobalUnread($this->link, $uid);
+
+                       if ($fresh) {
+                               print ";";
+                               print getFeedArticles($this->link, -3, false, true, $uid);
+                       }
+
+               } else {
+                       print "-1;User not found";
+               }
+
+       }
+
+       function getProfiles() {
+               $login = db_escape_string($_REQUEST["login"]);
+               $password = db_escape_string($_REQUEST["password"]);
+
+               if (authenticate_user($this->link, $login, $password)) {
+                       $result = db_query($this->link, "SELECT * FROM ttrss_settings_profiles
+                               WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY title");
+
+                       print "<select style='width: 100%' name='profile'>";
+
+                       print "<option value='0'>" . __("Default profile") . "</option>";
+
+                       while ($line = db_fetch_assoc($result)) {
+                               $id = $line["id"];
+                               $title = $line["title"];
+
+                               print "<option value='$id'>$title</option>";
+                       }
+
+                       print "</select>";
+
+                       $_SESSION = array();
+               }
+       }
+
+       function pubsub() {
+               $mode = db_escape_string($_REQUEST['hub_mode']);
+               $feed_id = (int) db_escape_string($_REQUEST['id']);
+               $feed_url = db_escape_string($_REQUEST['hub_topic']);
+
+               if (!PUBSUBHUBBUB_ENABLED) {
+                       header('HTTP/1.0 404 Not Found');
+                       echo "404 Not found";
+                       return;
+               }
+
+               // TODO: implement hub_verifytoken checking
+
+               $result = db_query($this->link, "SELECT feed_url FROM ttrss_feeds
+                       WHERE id = '$feed_id'");
+
+               if (db_num_rows($result) != 0) {
+
+                       $check_feed_url = db_fetch_result($result, 0, "feed_url");
+
+                       if ($check_feed_url && ($check_feed_url == $feed_url || !$feed_url)) {
+                               if ($mode == "subscribe") {
+
+                                       db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 2
+                                               WHERE id = '$feed_id'");
+
+                                       print $_REQUEST['hub_challenge'];
+                                       return;
+
+                               } else if ($mode == "unsubscribe") {
+
+                                       db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0
+                                               WHERE id = '$feed_id'");
+
+                                       print $_REQUEST['hub_challenge'];
+                                       return;
+
+                               } else if (!$mode) {
+
+                                       // Received update ping, schedule feed update.
+                                       //update_rss_feed($this->link, $feed_id, true, true);
+
+                                       db_query($this->link, "UPDATE ttrss_feeds SET
+                                               last_update_started = '1970-01-01',
+                                               last_updated = '1970-01-01' WHERE id = '$feed_id'");
+
+                               }
+                       } else {
+                               header('HTTP/1.0 404 Not Found');
+                               echo "404 Not found";
+                       }
+               } else {
+                       header('HTTP/1.0 404 Not Found');
+                       echo "404 Not found";
+               }
+
+       }
+
+       function logout() {
+               logout_user();
+               header("Location: index.php");
+       }
+
+       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)));
+               }
+       }
+
+       function share() {
+               $uuid = db_escape_string($_REQUEST["key"]);
+
+               $result = db_query($this->link, "SELECT ref_id, owner_uid FROM ttrss_user_entries WHERE
+                       uuid = '$uuid'");
+
+               if (db_num_rows($result) != 0) {
+                       header("Content-Type: text/html");
+
+                       $id = db_fetch_result($result, 0, "ref_id");
+                       $owner_uid = db_fetch_result($result, 0, "owner_uid");
+
+                       $article = format_article($this->link, $id, false, true, $owner_uid);
+
+                       print_r($article['content']);
+
+               } else {
+                       print "Article not found.";
+               }
+
+       }
+
+       function rss() {
+               header("Content-Type: text/xml; charset=utf-8");
+
+               $feed = db_escape_string($_REQUEST["id"]);
+               $key = db_escape_string($_REQUEST["key"]);
+               $is_cat = $_REQUEST["is_cat"] != false;
+               $limit = (int)db_escape_string($_REQUEST["limit"]);
+
+               $search = db_escape_string($_REQUEST["q"]);
+               $match_on = db_escape_string($_REQUEST["m"]);
+               $search_mode = db_escape_string($_REQUEST["smode"]);
+               $view_mode = db_escape_string($_REQUEST["view-mode"]);
+
+               if (SINGLE_USER_MODE) {
+                       authenticate_user($this->link, "admin", null);
+               }
+
+               $owner_id = false;
+
+               if ($key) {
+                       $result = db_query($this->link, "SELECT owner_uid FROM
+                               ttrss_access_keys WHERE access_key = '$key' AND feed_id = '$feed'");
+
+                       if (db_num_rows($result) == 1)
+                               $owner_id = db_fetch_result($result, 0, "owner_uid");
+               }
+
+               if ($owner_id) {
+                       $this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
+                               $search, $search_mode, $match_on, $view_mode);
+               } else {
+                       header('HTTP/1.1 403 Forbidden');
+               }
+       }
+
+       function globalUpdateFeeds() {
+               include "rssfuncs.php";
+               // Update all feeds needing a update.
+               update_daemon_common($this->link, 0, true, false);
+       }
+}
+?>
diff --git a/classes/mail_button.php b/classes/mail_button.php
deleted file mode 100644 (file)
index b299cce..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-class Mail_Button extends Plugin_Button {
-       function render($article_id) {
-               return "<img src=\"".theme_image($link, 'images/art-email.png')."\"
-                                       class='tagsPic' style=\"cursor : pointer\"
-                                       onclick=\"emailArticle($article_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=\"rpc\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"buttonPlugin\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"mail\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin_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>";
-       }
-
-
-}
-?>
diff --git a/classes/note_button.php b/classes/note_button.php
deleted file mode 100644 (file)
index 794f177..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-class Note_Button extends Plugin_Button {
-       function render($article_id) {
-               return "<img src=\"".theme_image($this->link, "images/art-pub-note.png")."\"
-                               style=\"cursor : pointer\" style=\"cursor : pointer\"
-                               onclick=\"editArticleNote($article_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=\"rpc\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"buttonPlugin\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin\" value=\"note\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"plugin_method\" value=\"setNote\">";
-
-               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)));
-       }
-
-
-}
-?>
index af597caf446beab7c6fed284a0f53ac2ac9b3b3b..8683fb73a33a86b7a70fb8c6681d781ae4480a6f 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-class Opml extends Protected_Handler {
+class Opml extends Handler_Protected {
 
        function csrf_ignore($method) {
                $csrf_ignored = array("export", "import");
diff --git a/classes/plugin.php b/classes/plugin.php
new file mode 100644 (file)
index 0000000..b96874a
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+class Plugin {
+       protected $link;
+       protected $handler;
+
+       function __construct($link, $handler) {
+               $this->link = $link;
+               $this->handler = $handler;
+               $this->initialize();
+       }
+
+       function initialize() {
+
+
+       }
+
+       function add_listener($hook) {
+               $this->handler->add_listener($hook, $this);
+       }
+}
+?>
diff --git a/classes/plugin/example.php b/classes/plugin/example.php
new file mode 100644 (file)
index 0000000..e10781a
--- /dev/null
@@ -0,0 +1,11 @@
+<?
+       class Plugin_Example extends Plugin {
+               function initialize() {
+                       $this->add_listener('article_before');
+               }
+
+               function article_before(&$line) {
+                       $line["title"] = "EXAMPLE/REPLACED:" . $line["title"];
+               }
+       }
+?>
diff --git a/classes/plugin_button.php b/classes/plugin_button.php
deleted file mode 100644 (file)
index 6cb8ec1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-class Plugin_Button {
-
-       protected $link;
-
-       function __construct($link) {
-               $this->link = $link;
-       }
-
-}
-?>
diff --git a/classes/plugins.php b/classes/plugins.php
new file mode 100644 (file)
index 0000000..6f3720c
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+class Plugins {
+       protected $link;
+       protected $plugins;
+       protected $listeners;
+
+       function __construct($link) {
+               $this->link = $link;
+               $this->listeners = array();
+               $this->load_plugins();
+       }
+
+       function load_plugins() {
+               if (defined('_ENABLE_PLUGINS')) {
+                       $plugins = explode(",", _ENABLE_PLUGINS);
+
+                       foreach ($plugins as $p) {
+                               $plugin_class = "plugin_$p";
+                               if (class_exists($plugin_class)) {
+                                       $plugin = new $plugin_class($this->link, $this);
+                               }
+                       }
+               }
+       }
+
+       function add_listener($hook_name, $plugin) {
+               if (!is_array($this->listeners[$hook_name]))
+                       $this->listeners[$hook_name] = array();
+
+               array_push($this->listeners[$hook_name], $plugin);
+       }
+
+       function hook($hook_name, &$params) {
+               if (is_array($this->listeners[$hook_name])) {
+                       foreach ($this->listeners[$hook_name] as $p) {
+                               if (method_exists($p, $hook_name)) {
+                                       $p->$hook_name($params);
+                               }
+                       }
+               }
+       }
+
+}
+?>
diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php
new file mode 100644 (file)
index 0000000..5899115
--- /dev/null
@@ -0,0 +1,1681 @@
+<?php
+class Pref_Feeds extends Handler_Protected {
+
+       function csrf_ignore($method) {
+               $csrf_ignored = array("index", "getfeedtree", "add", "editcats", "editfeed",
+                       "savefeedorder", "uploadicon");
+
+               return array_search($method, $csrf_ignored) !== false;
+       }
+
+       function batch_edit_cbox($elem, $label = false) {
+               print "<input type=\"checkbox\" title=\"".__("Check to enable field")."\"
+                       onchange=\"dijit.byId('feedEditDlg').toggleField(this, '$elem', '$label')\">";
+       }
+
+       function renamecat() {
+               $title = db_escape_string($_REQUEST['title']);
+               $id = db_escape_string($_REQUEST['id']);
+
+               if ($title) {
+                       db_query($this->link, "UPDATE ttrss_feed_categories SET
+                               title = '$title' WHERE id = '$id' AND owner_uid = " . $_SESSION["uid"]);
+               }
+               return;
+       }
+
+       function remtwitterinfo() {
+
+               db_query($this->link, "UPDATE ttrss_users SET twitter_oauth = NULL
+                       WHERE id = " . $_SESSION['uid']);
+
+               return;
+       }
+
+       private function get_category_items($cat_id) {
+               $show_empty_cats = $_REQUEST['mode'] != 2 &&
+                       get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
+
+               $items = array();
+
+               $result = db_query($this->link, "SELECT id, title, collapsed FROM ttrss_feed_categories
+                               WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat = '$cat_id' ORDER BY order_id, title");
+
+               while ($line = db_fetch_assoc($result)) {
+
+                       $cat = array();
+                       $cat['id'] = 'CAT:' . $line['id'];
+                       $cat['bare_id'] = (int)$line['id'];
+                       $cat['name'] = $line['title'];
+                       $cat['items'] = array();
+                       $cat['checkbox'] = false;
+                       $cat['hidden'] = sql_bool_to_bool($line['collapsed']);
+                       $cat['type'] = 'category';
+                       $cat['unread'] = 0;
+                       $cat['child_unread'] = 0;
+
+                       $cat['items'] = $this->get_category_items($line['id']);
+
+                       $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
+
+                       if (count($cat['items']) > 0 || $show_empty_cats)
+                               array_push($items, $cat);
+
+               }
+
+               $feed_result = db_query($this->link, "SELECT id, title, last_error,
+                       ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
+                       FROM ttrss_feeds
+                       WHERE cat_id = '$cat_id' AND owner_uid = ".$_SESSION["uid"].
+                       "$search_qpart ORDER BY order_id, title");
+
+               while ($feed_line = db_fetch_assoc($feed_result)) {
+                       $feed = array();
+                       $feed['id'] = 'FEED:' . $feed_line['id'];
+                       $feed['bare_id'] = (int)$feed_line['id'];
+                       $feed['name'] = $feed_line['title'];
+                       $feed['checkbox'] = false;
+                       $feed['unread'] = 0;
+                       $feed['error'] = $feed_line['last_error'];
+                       $feed['icon'] = getFeedIcon($feed_line['id']);
+                       $feed['param'] = make_local_datetime($this->link,
+                               $feed_line['last_updated'], true);
+
+                       array_push($items, $feed);
+               }
+
+               return $items;
+       }
+
+       function getfeedtree() {
+
+               $search = $_SESSION["prefs_feed_search"];
+
+               if ($search) $search_qpart = " AND LOWER(title) LIKE LOWER('%$search%')";
+
+               $root = array();
+               $root['id'] = 'root';
+               $root['name'] = __('Feeds');
+               $root['items'] = array();
+               $root['type'] = 'category';
+
+               $enable_cats = get_pref($this->link, 'ENABLE_FEED_CATS');
+
+               if ($_REQUEST['mode'] == 2) {
+
+                       if ($enable_cats) {
+                               $cat_hidden = get_pref($this->link, "_COLLAPSED_SPECIAL");
+                               $cat = $this->feedlist_init_cat(-1, $cat_hidden);
+                       } else {
+                               $cat['items'] = array();
+                       }
+
+                       foreach (array(-4, -3, -1, -2, 0) as $i) {
+                               array_push($cat['items'], $this->feedlist_init_feed($i));
+                       }
+
+                       if ($enable_cats) {
+                               array_push($root['items'], $cat);
+                       } else {
+                               $root['items'] = array_merge($root['items'], $cat['items']);
+                       }
+
+                       $result = db_query($this->link, "SELECT * FROM
+                               ttrss_labels2 WHERE owner_uid = ".$_SESSION['uid']." ORDER by caption");
+
+                       if (db_num_rows($result) > 0) {
+
+                               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
+                                       $cat_hidden = get_pref($this->link, "_COLLAPSED_LABELS");
+                                       $cat = $this->feedlist_init_cat(-2, $cat_hidden);
+                               } else {
+                                       $cat['items'] = array();
+                               }
+
+                               while ($line = db_fetch_assoc($result)) {
+
+                                       $label_id = -$line['id'] - 11;
+                                       $count = getFeedUnread($this->link, $label_id);
+
+                                       $feed = $this->feedlist_init_feed($label_id, false, $count);
+
+                                       $feed['fg_color'] = $line['fg_color'];
+                                       $feed['bg_color'] = $line['bg_color'];
+
+                                       array_push($cat['items'], $feed);
+                               }
+
+                               if ($enable_cats) {
+                                       array_push($root['items'], $cat);
+                               } else {
+                                       $root['items'] = array_merge($root['items'], $cat['items']);
+                               }
+                       }
+               }
+
+               if ($enable_cats) {
+                       $show_empty_cats = $_REQUEST['mode'] != 2 &&
+                               get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
+
+                       $result = db_query($this->link, "SELECT id, title, collapsed FROM ttrss_feed_categories
+                               WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat IS NULL ORDER BY order_id, title");
+
+                       while ($line = db_fetch_assoc($result)) {
+                               $cat = array();
+                               $cat['id'] = 'CAT:' . $line['id'];
+                               $cat['bare_id'] = (int)$line['id'];
+                               $cat['name'] = $line['title'];
+                               $cat['items'] = array();
+                               $cat['checkbox'] = false;
+                               $cat['hidden'] = sql_bool_to_bool($line['collapsed']);
+                               $cat['type'] = 'category';
+                               $cat['unread'] = 0;
+                               $cat['child_unread'] = 0;
+
+                               $cat['items'] = $this->get_category_items($line['id']);
+
+                               $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
+
+                               if (count($cat['items']) > 0 || $show_empty_cats)
+                                       array_push($root['items'], $cat);
+
+                               $root['param'] += count($cat['items']);
+                       }
+
+                       /* Uncategorized is a special case */
+
+                       $cat = array();
+                       $cat['id'] = 'CAT:0';
+                       $cat['bare_id'] = 0;
+                       $cat['name'] = __("Uncategorized");
+                       $cat['items'] = array();
+                       $cat['hidden'] = get_pref($this->link, "_COLLAPSED_UNCAT");
+                       $cat['type'] = 'category';
+                       $cat['checkbox'] = false;
+                       $cat['unread'] = 0;
+                       $cat['child_unread'] = 0;
+
+                       $feed_result = db_query($this->link, "SELECT id, title,last_error,
+                               ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
+                               FROM ttrss_feeds
+                               WHERE cat_id IS NULL AND owner_uid = ".$_SESSION["uid"].
+                               "$search_qpart ORDER BY order_id, title");
+
+                       while ($feed_line = db_fetch_assoc($feed_result)) {
+                               $feed = array();
+                               $feed['id'] = 'FEED:' . $feed_line['id'];
+                               $feed['bare_id'] = (int)$feed_line['id'];
+                               $feed['name'] = $feed_line['title'];
+                               $feed['checkbox'] = false;
+                               $feed['error'] = $feed_line['last_error'];
+                               $feed['icon'] = getFeedIcon($feed_line['id']);
+                               $feed['param'] = make_local_datetime($this->link,
+                                       $feed_line['last_updated'], true);
+                               $feed['unread'] = 0;
+                               $feed['type'] = 'feed';
+
+                               array_push($cat['items'], $feed);
+                       }
+
+                       $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
+
+                       if (count($cat['items']) > 0 || $show_empty_cats)
+                               array_push($root['items'], $cat);
+
+                       $root['param'] += count($cat['items']);
+                       $root['param'] = T_sprintf('(%d feeds)', $root['param']);
+
+               } else {
+                       $feed_result = db_query($this->link, "SELECT id, title, last_error,
+                               ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
+                               FROM ttrss_feeds
+                               WHERE owner_uid = ".$_SESSION["uid"].
+                               "$search_qpart ORDER BY order_id, title");
+
+                       while ($feed_line = db_fetch_assoc($feed_result)) {
+                               $feed = array();
+                               $feed['id'] = 'FEED:' . $feed_line['id'];
+                               $feed['bare_id'] = (int)$feed_line['id'];
+                               $feed['name'] = $feed_line['title'];
+                               $feed['checkbox'] = false;
+                               $feed['error'] = $feed_line['last_error'];
+                               $feed['icon'] = getFeedIcon($feed_line['id']);
+                               $feed['param'] = make_local_datetime($this->link,
+                                       $feed_line['last_updated'], true);
+                               $feed['unread'] = 0;
+                               $feed['type'] = 'feed';
+
+                               array_push($root['items'], $feed);
+                       }
+
+                       $root['param'] = T_sprintf('(%d feeds)', count($root['items']));
+               }
+
+               $fl = array();
+               $fl['identifier'] = 'id';
+               $fl['label'] = 'name';
+
+               if ($_REQUEST['mode'] != 2) {
+                       $fl['items'] = array($root);
+               } else {
+                       $fl['items'] =& $root['items'];
+               }
+
+               print json_encode($fl);
+               return;
+       }
+
+       function catsortreset() {
+               db_query($this->link, "UPDATE ttrss_feed_categories
+                               SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
+               return;
+       }
+
+       function feedsortreset() {
+               db_query($this->link, "UPDATE ttrss_feeds
+                               SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
+               return;
+       }
+
+       function togglehiddenfeedcats() {
+               set_pref($this->link, '_PREFS_SHOW_EMPTY_CATS',
+                       (get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS') ? 'false' : 'true'));
+       }
+
+       private function process_category_order(&$data_map, $item_id, $parent_id = false, $nest_level = 0) {
+               $debug = isset($_REQUEST["debug"]);
+
+               $prefix = "";
+               for ($i = 0; $i < $nest_level; $i++)
+                       $prefix .= "   ";
+
+               if ($debug) _debug("$prefix C: $item_id P: $parent_id");
+
+               $bare_item_id = substr($item_id, strpos($item_id, ':')+1);
+
+               if ($item_id != 'root') {
+                       if ($parent_id && $parent_id != 'root') {
+                               $parent_bare_id = substr($parent_id, strpos($parent_id, ':')+1);
+                               $parent_qpart = db_escape_string($parent_bare_id);
+                       } else {
+                               $parent_qpart = 'NULL';
+                       }
+
+                       db_query($this->link, "UPDATE ttrss_feed_categories
+                               SET parent_cat = $parent_qpart WHERE id = '$bare_item_id' AND
+                               owner_uid = " . $_SESSION["uid"]);
+               }
+
+               $order_id = 0;
+
+               $cat = $data_map[$item_id];
+
+               if ($cat && is_array($cat)) {
+                       foreach ($cat as $item) {
+                               $id = $item['_reference'];
+                               $bare_id = substr($id, strpos($id, ':')+1);
+
+                               if ($debug) _debug("$prefix [$order_id] $id/$bare_id");
+
+                               if ($item['_reference']) {
+
+                                       if (strpos($id, "FEED") === 0) {
+
+                                               $cat_id = ($item_id != "root") ?
+                                                       db_escape_string($bare_item_id) : "NULL";
+
+                                               db_query($this->link, "UPDATE ttrss_feeds
+                                                       SET order_id = $order_id, cat_id = '$cat_id'
+                                                       WHERE id = '$bare_id' AND
+                                                               owner_uid = " . $_SESSION["uid"]);
+
+                                       } else if (strpos($id, "CAT:") === 0) {
+                                               $this->process_category_order($data_map, $item['_reference'], $item_id,
+                                                       $nest_level+1);
+
+                                               if ($item_id != 'root') {
+                                                       $parent_qpart = db_escape_string($bare_id);
+                                               } else {
+                                                       $parent_qpart = 'NULL';
+                                               }
+
+                                               db_query($this->link, "UPDATE ttrss_feed_categories
+                                                               SET order_id = '$order_id' WHERE id = '$bare_id' AND
+                                                               owner_uid = " . $_SESSION["uid"]);
+                                       }
+                               }
+
+                               ++$order_id;
+                       }
+               }
+       }
+
+       function savefeedorder() {
+               $data = json_decode($_POST['payload'], true);
+
+               #file_put_contents("/tmp/saveorder.json", $_POST['payload']);
+               #$data = json_decode(file_get_contents("/tmp/saveorder.json"), true);
+
+               if (!is_array($data['items']))
+                       $data['items'] = json_decode($data['items'], true);
+
+#              print_r($data['items']);
+
+               if (is_array($data) && is_array($data['items'])) {
+                       $cat_order_id = 0;
+
+                       $data_map = array();
+                       $root_item = false;
+
+                       foreach ($data['items'] as $item) {
+
+#                              if ($item['id'] != 'root') {
+                                       if (is_array($item['items'])) {
+                                               if (isset($item['items']['_reference'])) {
+                                                       $data_map[$item['id']] = array($item['items']);
+                                               } else {
+                                                       $data_map[$item['id']] =& $item['items'];
+                                               }
+                                       }
+                               if ($item['id'] == 'root') {
+                                       $root_item = $item['id'];
+                               }
+                       }
+
+                       $this->process_category_order($data_map, $root_item);
+
+                       /* foreach ($data['items'][0]['items'] as $item) {
+                               $id = $item['_reference'];
+                               $bare_id = substr($id, strpos($id, ':')+1);
+
+                               ++$cat_order_id;
+
+                               if ($bare_id > 0) {
+                                       db_query($this->link, "UPDATE ttrss_feed_categories
+                                               SET order_id = '$cat_order_id' WHERE id = '$bare_id' AND
+                                               owner_uid = " . $_SESSION["uid"]);
+                               }
+
+                               $feed_order_id = 0;
+
+                               if (is_array($data_map[$id])) {
+                                       foreach ($data_map[$id] as $feed) {
+                                               $id = $feed['_reference'];
+                                               $feed_id = substr($id, strpos($id, ':')+1);
+
+                                               if ($bare_id != 0)
+                                                       $cat_query = "cat_id = '$bare_id'";
+                                               else
+                                                       $cat_query = "cat_id = NULL";
+
+                                               db_query($this->link, "UPDATE ttrss_feeds
+                                                       SET order_id = '$feed_order_id',
+                                                       $cat_query
+                                                       WHERE id = '$feed_id' AND
+                                                               owner_uid = " . $_SESSION["uid"]);
+
+                                               ++$feed_order_id;
+                                       }
+                               }
+                       } */
+               }
+
+               return;
+       }
+
+       function removeicon() {
+               $feed_id = db_escape_string($_REQUEST["feed_id"]);
+
+               $result = db_query($this->link, "SELECT id FROM ttrss_feeds
+                       WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
+
+               if (db_num_rows($result) != 0) {
+                       unlink(ICONS_DIR . "/$feed_id.ico");
+               }
+
+               return;
+       }
+
+       function uploadicon() {
+               $icon_file = $_FILES['icon_file']['tmp_name'];
+               $feed_id = db_escape_string($_REQUEST["feed_id"]);
+
+               if (is_file($icon_file) && $feed_id) {
+                       if (filesize($icon_file) < 20000) {
+
+                               $result = db_query($this->link, "SELECT id FROM ttrss_feeds
+                                       WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
+
+                               if (db_num_rows($result) != 0) {
+                                       unlink(ICONS_DIR . "/$feed_id.ico");
+                                       move_uploaded_file($icon_file, ICONS_DIR . "/$feed_id.ico");
+                                       $rc = 0;
+                               } else {
+                                       $rc = 2;
+                               }
+                       } else {
+                               $rc = 1;
+                       }
+               } else {
+                       $rc = 2;
+               }
+
+               print "<script type=\"text/javascript\">";
+               print "parent.uploadIconHandler($rc);";
+               print "</script>";
+               return;
+       }
+
+       function editfeed() {
+               global $purge_intervals;
+               global $update_intervals;
+               global $update_methods;
+
+               $feed_id = db_escape_string($_REQUEST["id"]);
+
+               $result = db_query($this->link,
+                       "SELECT * FROM ttrss_feeds WHERE id = '$feed_id' AND
+                               owner_uid = " . $_SESSION["uid"]);
+
+               $title = htmlspecialchars(db_fetch_result($result,
+                       0, "title"));
+
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$feed_id\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"editSave\">";
+
+               print "<div class=\"dlgSec\">".__("Feed")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               /* Title */
+
+               print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
+                       placeHolder=\"".__("Feed Title")."\"
+                       style=\"font-size : 16px; width: 20em\" name=\"title\" value=\"$title\">";
+
+               /* Feed URL */
+
+               $feed_url = db_fetch_result($result, 0, "feed_url");
+               $feed_url = htmlspecialchars(db_fetch_result($result,
+                       0, "feed_url"));
+
+               print "<hr/>";
+
+               print __('URL:') . " ";
+               print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
+                       placeHolder=\"".__("Feed URL")."\"
+                       regExp='^(http|https)://.*' style=\"width : 20em\"
+                       name=\"feed_url\" value=\"$feed_url\">";
+
+               $last_error = db_fetch_result($result, 0, "last_error");
+
+               if ($last_error) {
+                       print "&nbsp;<span title=\"".htmlspecialchars($last_error)."\"
+                               class=\"feed_error\">(error)</span>";
+
+               }
+
+               /* Category */
+
+               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
+
+                       $cat_id = db_fetch_result($result, 0, "cat_id");
+
+                       print "<hr/>";
+
+                       print __('Place in category:') . " ";
+
+                       print_feed_cat_select($this->link, "cat_id", $cat_id,
+                               'dojoType="dijit.form.Select"');
+               }
+
+               print "</div>";
+
+               print "<div class=\"dlgSec\">".__("Update")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               /* Update Interval */
+
+               $update_interval = db_fetch_result($result, 0, "update_interval");
+
+               print_select_hash("update_interval", $update_interval, $update_intervals,
+                       'dojoType="dijit.form.Select"');
+
+               /* Update method */
+
+               $update_method = db_fetch_result($result, 0, "update_method",
+                       'dojoType="dijit.form.Select"');
+
+               print " " . __('using') . " ";
+               print_select_hash("update_method", $update_method, $update_methods,
+                       'dojoType="dijit.form.Select"');
+
+               $purge_interval = db_fetch_result($result, 0, "purge_interval");
+
+
+                       /* Purge intl */
+
+               print "<hr/>";
+               print __('Article purging:') . " ";
+
+               print_select_hash("purge_interval", $purge_interval, $purge_intervals,
+                       'dojoType="dijit.form.Select" ' .
+                               ((FORCE_ARTICLE_PURGE == 0) ? "" : 'disabled="1"'));
+
+               print "</div>";
+               print "<div class=\"dlgSec\">".__("Authentication")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               $auth_login = htmlspecialchars(db_fetch_result($result, 0, "auth_login"));
+
+               print "<input dojoType=\"dijit.form.TextBox\" id=\"feedEditDlg_login\"
+                       placeHolder=\"".__("Login")."\"
+                       name=\"auth_login\" value=\"$auth_login\"><hr/>";
+
+               $auth_pass = htmlspecialchars(db_fetch_result($result, 0, "auth_pass"));
+
+               print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
+                       placeHolder=\"".__("Password")."\"
+                       value=\"$auth_pass\">";
+
+               print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedEditDlg_login\" position=\"below\">
+                       ".__('<b>Hint:</b> you need to fill in your login information if your feed requires authentication, except for Twitter feeds.')."
+                       </div>";
+
+               print "</div>";
+               print "<div class=\"dlgSec\">".__("Options")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               $private = sql_bool_to_bool(db_fetch_result($result, 0, "private"));
+
+               if ($private) {
+                       $checked = "checked=\"1\"";
+               } else {
+                       $checked = "";
+               }
+
+               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"private\" id=\"private\"
+                       $checked>&nbsp;<label for=\"private\">".__('Hide from Popular feeds')."</label>";
+
+               $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
+
+               if ($rtl_content) {
+                       $checked = "checked=\"1\"";
+               } else {
+                       $checked = "";
+               }
+
+               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
+                       $checked>&nbsp;<label for=\"rtl_content\">".__('Right-to-left content')."</label>";
+
+               $include_in_digest = sql_bool_to_bool(db_fetch_result($result, 0, "include_in_digest"));
+
+               if ($include_in_digest) {
+                       $checked = "checked=\"1\"";
+               } else {
+                       $checked = "";
+               }
+
+               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"include_in_digest\"
+                       name=\"include_in_digest\"
+                       $checked>&nbsp;<label for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
+
+
+               $always_display_enclosures = sql_bool_to_bool(db_fetch_result($result, 0, "always_display_enclosures"));
+
+               if ($always_display_enclosures) {
+                       $checked = "checked";
+               } else {
+                       $checked = "";
+               }
+
+               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"always_display_enclosures\"
+                       name=\"always_display_enclosures\"
+                       $checked>&nbsp;<label for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
+
+
+               $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
+
+               if ($cache_images) {
+                       $checked = "checked=\"1\"";
+               } else {
+                       $checked = "";
+               }
+
+               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"cache_images\"
+               name=\"cache_images\"
+                       $checked>&nbsp;<label for=\"cache_images\">".
+               __('Cache images locally')."</label>";
+
+               $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
+
+               if ($mark_unread_on_update) {
+                       $checked = "checked";
+               } else {
+                       $checked = "";
+               }
+
+               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"mark_unread_on_update\"
+                       name=\"mark_unread_on_update\"
+                       $checked>&nbsp;<label for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
+
+               $update_on_checksum_change = sql_bool_to_bool(db_fetch_result($result, 0, "update_on_checksum_change"));
+
+               if ($update_on_checksum_change) {
+                       $checked = "checked";
+               } else {
+                       $checked = "";
+               }
+
+               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"update_on_checksum_change\"
+                       name=\"update_on_checksum_change\"
+                       $checked>&nbsp;<label for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
+
+               print "</div>";
+
+               /* Icon */
+
+               print "<div class=\"dlgSec\">".__("Icon")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               print "<iframe name=\"icon_upload_iframe\"
+                       style=\"width: 400px; height: 100px; display: none;\"></iframe>";
+
+               print "<form style='display : block' target=\"icon_upload_iframe\"
+                       enctype=\"multipart/form-data\" method=\"POST\"
+                       action=\"backend.php\">
+                       <input id=\"icon_file\" size=\"10\" name=\"icon_file\" type=\"file\">
+                       <input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
+                       <input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
+                       <input type=\"hidden\" name=\"method\" value=\"uploadicon\">
+                       <button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
+                               type=\"submit\">".__('Replace')."</button>
+                       <button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
+                               type=\"submit\">".__('Remove')."</button>
+                       </form>";
+
+               print "</div>";
+
+               $title = htmlspecialchars($title, ENT_QUOTES);
+
+               print "<div class='dlgButtons'>
+                       <div style=\"float : left\">
+                       <button dojoType=\"dijit.form.Button\" onclick='return unsubscribeFeed($feed_id, \"$title\")'>".
+                               __('Unsubscribe')."</button>";
+
+               if (PUBSUBHUBBUB_ENABLED) {
+                       $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
+                       $pubsub_btn_disabled = ($pubsub_state == 2) ? "" : "disabled=\"1\"";
+
+                       print "<button dojoType=\"dijit.form.Button\" id=\"pubsubReset_Btn\" $pubsub_btn_disabled
+                                       onclick='return resetPubSub($feed_id, \"$title\")'>".__('Resubscribe to push updates').
+                                       "</button>";
+               }
+
+               print "</div>";
+
+               print "<div dojoType=\"dijit.Tooltip\" connectId=\"pubsubReset_Btn\" position=\"below\">".
+                       __('Resets PubSubHubbub subscription status for push-enabled feeds.')."</div>";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').execute()\">".__('Save')."</button>
+                       <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').hide()\">".__('Cancel')."</button>
+               </div>";
+
+               return;
+       }
+
+       function editfeeds() {
+               global $purge_intervals;
+               global $update_intervals;
+               global $update_methods;
+
+               $feed_ids = db_escape_string($_REQUEST["ids"]);
+
+               print "<div class=\"dialogNotice\">" . __("Enable the options you wish to apply using checkboxes on the right:") . "</div>";
+
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"ids\" value=\"$feed_ids\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"batchEditSave\">";
+
+               print "<div class=\"dlgSec\">".__("Feed")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               /* Title */
+
+               print "<input dojoType=\"dijit.form.ValidationTextBox\"
+                       disabled=\"1\" style=\"font-size : 16px; width : 20em;\" required=\"1\"
+                       name=\"title\" value=\"$title\">";
+
+               $this->batch_edit_cbox("title");
+
+               /* Feed URL */
+
+               print "<br/>";
+
+               print __('URL:') . " ";
+               print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\"
+                       required=\"1\" regExp='^(http|https)://.*' style=\"width : 20em\"
+                       name=\"feed_url\" value=\"$feed_url\">";
+
+               $this->batch_edit_cbox("feed_url");
+
+               /* Category */
+
+               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
+
+                       print "<br/>";
+
+                       print __('Place in category:') . " ";
+
+                       print_feed_cat_select($this->link, "cat_id", $cat_id,
+                               'disabled="1" dojoType="dijit.form.Select"');
+
+                       $this->batch_edit_cbox("cat_id");
+
+               }
+
+               print "</div>";
+
+               print "<div class=\"dlgSec\">".__("Update")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               /* Update Interval */
+
+               print_select_hash("update_interval", $update_interval, $update_intervals,
+                       'disabled="1" dojoType="dijit.form.Select"');
+
+               $this->batch_edit_cbox("update_interval");
+
+               /* Update method */
+
+               print " " . __('using') . " ";
+               print_select_hash("update_method", $update_method, $update_methods,
+                       'disabled="1" dojoType="dijit.form.Select"');
+               $this->batch_edit_cbox("update_method");
+
+               /* Purge intl */
+
+               if (FORCE_ARTICLE_PURGE == 0) {
+
+                       print "<br/>";
+
+                       print __('Article purging:') . " ";
+
+                       print_select_hash("purge_interval", $purge_interval, $purge_intervals,
+                               'disabled="1" dojoType="dijit.form.Select"');
+
+                       $this->batch_edit_cbox("purge_interval");
+               }
+
+               print "</div>";
+               print "<div class=\"dlgSec\">".__("Authentication")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               print "<input dojoType=\"dijit.form.TextBox\"
+                       placeHolder=\"".__("Login")."\" disabled=\"1\"
+                       name=\"auth_login\" value=\"$auth_login\">";
+
+               $this->batch_edit_cbox("auth_login");
+
+               print "<br/><input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
+                       placeHolder=\"".__("Password")."\" disabled=\"1\"
+                       value=\"$auth_pass\">";
+
+               $this->batch_edit_cbox("auth_pass");
+
+               print "</div>";
+               print "<div class=\"dlgSec\">".__("Options")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               print "<input disabled=\"1\" type=\"checkbox\" name=\"private\" id=\"private\"
+                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"private_l\" class='insensitive' for=\"private\">".__('Hide from Popular feeds')."</label>";
+
+               print "&nbsp;"; $this->batch_edit_cbox("private", "private_l");
+
+               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
+                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"rtl_content_l\" for=\"rtl_content\">".__('Right-to-left content')."</label>";
+
+               print "&nbsp;"; $this->batch_edit_cbox("rtl_content", "rtl_content_l");
+
+               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"include_in_digest\"
+                       name=\"include_in_digest\"
+                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"include_in_digest_l\" class='insensitive' for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
+
+               print "&nbsp;"; $this->batch_edit_cbox("include_in_digest", "include_in_digest_l");
+
+               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"always_display_enclosures\"
+                       name=\"always_display_enclosures\"
+                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"always_display_enclosures_l\" class='insensitive' for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
+
+               print "&nbsp;"; $this->batch_edit_cbox("always_display_enclosures", "always_display_enclosures_l");
+
+               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"cache_images\"
+                       name=\"cache_images\"
+                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"cache_images_l\"
+                       for=\"cache_images\">".
+               __('Cache images locally')."</label>";
+
+               print "&nbsp;"; $this->batch_edit_cbox("cache_images", "cache_images_l");
+
+               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"mark_unread_on_update\"
+                       name=\"mark_unread_on_update\"
+                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"mark_unread_on_update_l\" class='insensitive' for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
+
+               print "&nbsp;"; $this->batch_edit_cbox("mark_unread_on_update", "mark_unread_on_update_l");
+
+               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"update_on_checksum_change\"
+                       name=\"update_on_checksum_change\"
+                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"update_on_checksum_change_l\" class='insensitive' for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
+
+               print "&nbsp;"; $this->batch_edit_cbox("update_on_checksum_change", "update_on_checksum_change_l");
+
+               print "</div>";
+
+               print "<div class='dlgButtons'>
+                       <button dojoType=\"dijit.form.Button\"
+                               onclick=\"return dijit.byId('feedEditDlg').execute()\">".
+                               __('Save')."</button>
+                       <button dojoType=\"dijit.form.Button\"
+                       onclick=\"return dijit.byId('feedEditDlg').hide()\">".
+                               __('Cancel')."</button>
+                       </div>";
+
+               return;
+       }
+
+       function batchEditSave() {
+               return $this->editsaveops(true);
+       }
+
+       function editSave() {
+               return $this->editsaveops(false);
+       }
+
+       function editsaveops($batch) {
+
+               $feed_title = db_escape_string(trim($_POST["title"]));
+               $feed_link = db_escape_string(trim($_POST["feed_url"]));
+               $upd_intl = (int) db_escape_string($_POST["update_interval"]);
+               $purge_intl = (int) db_escape_string($_POST["purge_interval"]);
+               $feed_id = (int) db_escape_string($_POST["id"]); /* editSave */
+               $feed_ids = db_escape_string($_POST["ids"]); /* batchEditSave */
+               $cat_id = (int) db_escape_string($_POST["cat_id"]);
+               $auth_login = db_escape_string(trim($_POST["auth_login"]));
+               $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
+               $private = checkbox_to_sql_bool(db_escape_string($_POST["private"]));
+               $rtl_content = checkbox_to_sql_bool(db_escape_string($_POST["rtl_content"]));
+               $include_in_digest = checkbox_to_sql_bool(
+                       db_escape_string($_POST["include_in_digest"]));
+               $cache_images = checkbox_to_sql_bool(
+                       db_escape_string($_POST["cache_images"]));
+               $update_method = (int) db_escape_string($_POST["update_method"]);
+
+               $always_display_enclosures = checkbox_to_sql_bool(
+                       db_escape_string($_POST["always_display_enclosures"]));
+
+               $mark_unread_on_update = checkbox_to_sql_bool(
+                       db_escape_string($_POST["mark_unread_on_update"]));
+
+               $update_on_checksum_change = checkbox_to_sql_bool(
+                       db_escape_string($_POST["update_on_checksum_change"]));
+
+               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
+                       if ($cat_id && $cat_id != 0) {
+                               $category_qpart = "cat_id = '$cat_id',";
+                               $category_qpart_nocomma = "cat_id = '$cat_id'";
+                       } else {
+                               $category_qpart = 'cat_id = NULL,';
+                               $category_qpart_nocomma = 'cat_id = NULL';
+                       }
+               } else {
+                       $category_qpart = "";
+                       $category_qpart_nocomma = "";
+               }
+
+               $cache_images_qpart = "cache_images = $cache_images,";
+
+               if (!$batch) {
+
+                       $result = db_query($this->link, "UPDATE ttrss_feeds SET
+                               $category_qpart
+                               title = '$feed_title', feed_url = '$feed_link',
+                               update_interval = '$upd_intl',
+                               purge_interval = '$purge_intl',
+                               auth_login = '$auth_login',
+                               auth_pass = '$auth_pass',
+                               private = $private,
+                               rtl_content = $rtl_content,
+                               $cache_images_qpart
+                               include_in_digest = $include_in_digest,
+                               always_display_enclosures = $always_display_enclosures,
+                               mark_unread_on_update = $mark_unread_on_update,
+                               update_on_checksum_change = $update_on_checksum_change,
+                               update_method = '$update_method'
+                               WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
+
+               } else {
+                       $feed_data = array();
+
+                       foreach (array_keys($_POST) as $k) {
+                               if ($k != "op" && $k != "method" && $k != "ids") {
+                                       $feed_data[$k] = $_POST[$k];
+                               }
+                       }
+
+                       db_query($this->link, "BEGIN");
+
+                       foreach (array_keys($feed_data) as $k) {
+
+                               $qpart = "";
+
+                               switch ($k) {
+                                       case "title":
+                                               $qpart = "title = '$feed_title'";
+                                               break;
+
+                                       case "feed_url":
+                                               $qpart = "feed_url = '$feed_link'";
+                                               break;
+
+                                       case "update_interval":
+                                               $qpart = "update_interval = '$upd_intl'";
+                                               break;
+
+                                       case "purge_interval":
+                                               $qpart = "purge_interval = '$purge_intl'";
+                                               break;
+
+                                       case "auth_login":
+                                               $qpart = "auth_login = '$auth_login'";
+                                               break;
+
+                                       case "auth_pass":
+                                               $qpart = "auth_pass = '$auth_pass'";
+                                               break;
+
+                                       case "private":
+                                               $qpart = "private = $private";
+                                               break;
+
+                                       case "include_in_digest":
+                                               $qpart = "include_in_digest = $include_in_digest";
+                                               break;
+
+                                       case "always_display_enclosures":
+                                               $qpart = "always_display_enclosures = $always_display_enclosures";
+                                               break;
+
+                                       case "mark_unread_on_update":
+                                               $qpart = "mark_unread_on_update = $mark_unread_on_update";
+                                               break;
+
+                                       case "update_on_checksum_change":
+                                               $qpart = "update_on_checksum_change = $update_on_checksum_change";
+                                               break;
+
+                                       case "cache_images":
+                                               $qpart = "cache_images = $cache_images";
+                                               break;
+
+                                       case "rtl_content":
+                                               $qpart = "rtl_content = $rtl_content";
+                                               break;
+
+                                       case "update_method":
+                                               $qpart = "update_method = '$update_method'";
+                                               break;
+
+                                       case "cat_id":
+                                               $qpart = $category_qpart_nocomma;
+                                               break;
+
+                               }
+
+                               if ($qpart) {
+                                       db_query($this->link,
+                                               "UPDATE ttrss_feeds SET $qpart WHERE id IN ($feed_ids)
+                                               AND owner_uid = " . $_SESSION["uid"]);
+                                       print "<br/>";
+                               }
+                       }
+
+                       db_query($this->link, "COMMIT");
+               }
+               return;
+       }
+
+       function resetPubSub() {
+
+               $ids = db_escape_string($_REQUEST["ids"]);
+
+               db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0 WHERE id IN ($ids)
+                       AND owner_uid = " . $_SESSION["uid"]);
+
+               return;
+       }
+
+       function remove() {
+
+               $ids = split(",", db_escape_string($_REQUEST["ids"]));
+
+               foreach ($ids as $id) {
+                       remove_feed($this->link, $id, $_SESSION["uid"]);
+               }
+
+               return;
+       }
+
+       function clear() {
+               $id = db_escape_string($_REQUEST["id"]);
+               clear_feed_articles($this->link, $id);
+       }
+
+       function rescore() {
+               $ids = split(",", db_escape_string($_REQUEST["ids"]));
+
+               foreach ($ids as $id) {
+
+                       $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
+
+                       $result = db_query($this->link, "SELECT
+                               title, content, link, ref_id, author,".
+                               SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
+                               FROM
+                                       ttrss_user_entries, ttrss_entries
+                                       WHERE ref_id = id AND feed_id = '$id' AND
+                                               owner_uid = " .$_SESSION['uid']."
+                                       ");
+
+                       $scores = array();
+
+                       while ($line = db_fetch_assoc($result)) {
+
+                               $tags = get_article_tags($this->link, $line["ref_id"]);
+
+                               $article_filters = get_article_filters($filters, $line['title'],
+                                       $line['content'], $line['link'], strtotime($line['updated']),
+                                       $line['author'], $tags);
+
+                               $new_score = calculate_article_score($article_filters);
+
+                               if (!$scores[$new_score]) $scores[$new_score] = array();
+
+                               array_push($scores[$new_score], $line['ref_id']);
+                       }
+
+                       foreach (array_keys($scores) as $s) {
+                               if ($s > 1000) {
+                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
+                                               marked = true WHERE
+                                               ref_id IN (" . join(',', $scores[$s]) . ")");
+                               } else if ($s < -500) {
+                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
+                                               unread = false WHERE
+                                               ref_id IN (" . join(',', $scores[$s]) . ")");
+                               } else {
+                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
+                                               ref_id IN (" . join(',', $scores[$s]) . ")");
+                               }
+                       }
+               }
+
+               print __("All done.");
+
+       }
+
+       function rescoreAll() {
+
+               $result = db_query($this->link,
+                       "SELECT id FROM ttrss_feeds WHERE owner_uid = " . $_SESSION['uid']);
+
+               while ($feed_line = db_fetch_assoc($result)) {
+
+                       $id = $feed_line["id"];
+
+                       $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
+
+                       $tmp_result = db_query($this->link, "SELECT
+                               title, content, link, ref_id, author,".
+                                       SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
+                                       FROM
+                                       ttrss_user_entries, ttrss_entries
+                                       WHERE ref_id = id AND feed_id = '$id' AND
+                                               owner_uid = " .$_SESSION['uid']."
+                                       ");
+
+                       $scores = array();
+
+                       while ($line = db_fetch_assoc($tmp_result)) {
+
+                               $tags = get_article_tags($this->link, $line["ref_id"]);
+
+                               $article_filters = get_article_filters($filters, $line['title'],
+                                       $line['content'], $line['link'], strtotime($line['updated']),
+                                       $line['author'], $tags);
+
+                               $new_score = calculate_article_score($article_filters);
+
+                               if (!$scores[$new_score]) $scores[$new_score] = array();
+
+                               array_push($scores[$new_score], $line['ref_id']);
+                       }
+
+                       foreach (array_keys($scores) as $s) {
+                               if ($s > 1000) {
+                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
+                                               marked = true WHERE
+                                               ref_id IN (" . join(',', $scores[$s]) . ")");
+                               } else {
+                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
+                                               ref_id IN (" . join(',', $scores[$s]) . ")");
+                               }
+                       }
+               }
+
+               print __("All done.");
+
+       }
+
+       function add() {
+               $feed_url = db_escape_string(trim($_REQUEST["feed_url"]));
+               $cat_id = db_escape_string($_REQUEST["cat_id"]);
+               $p_from = db_escape_string($_REQUEST["from"]);
+
+               /* only read authentication information from POST */
+
+               $auth_login = db_escape_string(trim($_POST["auth_login"]));
+               $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
+
+               if ($p_from != 'tt-rss') {
+                       header('Content-Type: text/html; charset=utf-8');
+                       print "<html>
+                               <head>
+                                       <title>Tiny Tiny RSS</title>
+                                       <link rel=\"stylesheet\" type=\"text/css\" href=\"utility.css\">
+                                       <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
+                               </head>
+                               <body>
+                               <img class=\"floatingLogo\" src=\"images/logo_wide.png\"
+                                       alt=\"Tiny Tiny RSS\"/>
+                               <h1>Subscribe to feed...</h1>";
+               }
+
+               $rc = subscribe_to_feed($this->link, $feed_url, $cat_id, $auth_login, $auth_pass);
+
+               switch ($rc) {
+               case 1:
+                       print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
+                       break;
+               case 2:
+                       print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
+                       break;
+               case 3:
+                       print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
+                       break;
+               case 0:
+                       print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
+                       break;
+               case 4:
+                       print_notice(__("Multiple feed URLs found."));
+
+                       $feed_urls = get_feeds_from_html($feed_url);
+                       break;
+               case 5:
+                       print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
+                       break;
+               }
+
+               if ($p_from != 'tt-rss') {
+
+                       if ($feed_urls) {
+
+                               print "<form action=\"backend.php\">";
+                               print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
+                               print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
+                               print "<input type=\"hidden\" name=\"method\" value=\"add\">";
+
+                               print "<select name=\"feed_url\">";
+
+                               foreach ($feed_urls as $url => $name) {
+                                       $url = htmlspecialchars($url);
+                                       $name = htmlspecialchars($name);
+
+                                       print "<option value=\"$url\">$name</option>";
+                               }
+
+                               print "<input type=\"submit\" value=\"".__("Subscribe to selected feed").
+                                       "\">";
+
+                               print "</form>";
+                       }
+
+                       $tp_uri = get_self_url_prefix() . "/prefs.php";
+                       $tt_uri = get_self_url_prefix();
+
+                       if ($rc <= 2){
+                               $result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
+                                       feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
+
+                               $feed_id = db_fetch_result($result, 0, "id");
+                       } else {
+                               $feed_id = 0;
+                       }
+                       print "<p>";
+
+                       if ($feed_id) {
+                               print "<form method=\"GET\" style='display: inline'
+                                       action=\"$tp_uri\">
+                                       <input type=\"hidden\" name=\"tab\" value=\"feedConfig\">
+                                       <input type=\"hidden\" name=\"method\" value=\"editFeed\">
+                                       <input type=\"hidden\" name=\"methodparam\" value=\"$feed_id\">
+                                       <input type=\"submit\" value=\"".__("Edit subscription options")."\">
+                                       </form>";
+                       }
+
+                       print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
+                               <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
+                               </form></p>";
+
+                       print "</body></html>";
+                       return;
+               }
+       }
+
+       function categorize() {
+               $ids = split(",", db_escape_string($_REQUEST["ids"]));
+
+               $cat_id = db_escape_string($_REQUEST["cat_id"]);
+
+               if ($cat_id == 0) {
+                       $cat_id_qpart = 'NULL';
+               } else {
+                       $cat_id_qpart = "'$cat_id'";
+               }
+
+               db_query($this->link, "BEGIN");
+
+               foreach ($ids as $id) {
+
+                       db_query($this->link, "UPDATE ttrss_feeds SET cat_id = $cat_id_qpart
+                               WHERE id = '$id'
+                               AND owner_uid = " . $_SESSION["uid"]);
+
+               }
+
+               db_query($this->link, "COMMIT");
+       }
+
+       function removeCat() {
+               $ids = split(",", db_escape_string($_REQUEST["ids"]));
+               foreach ($ids as $id) {
+                       remove_feed_category($this->link, $id, $_SESSION["uid"]);
+               }
+       }
+
+       function addCat() {
+               $feed_cat = db_escape_string(trim($_REQUEST["cat"]));
+
+               add_feed_category($this->link, $feed_cat);
+       }
+
+       function index() {
+
+               print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
+               print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Feeds')."\">";
+
+               $result = db_query($this->link, "SELECT COUNT(id) AS num_errors
+                       FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
+
+               $num_errors = db_fetch_result($result, 0, "num_errors");
+
+               if ($num_errors > 0) {
+
+                       $error_button = "<button dojoType=\"dijit.form.Button\"
+                                       onclick=\"showFeedsWithErrors()\" id=\"errorButton\">" .
+                               __("Feeds with errors") . "</button>";
+               }
+
+               if (DB_TYPE == "pgsql") {
+                       $interval_qpart = "NOW() - INTERVAL '3 months'";
+               } else {
+                       $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
+               }
+
+               $result = db_query($this->link, "SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
+                                       (SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
+                                               ttrss_entries.id = ref_id AND
+                                                       ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
+                       ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
+
+               $num_inactive = db_fetch_result($result, 0, "num_inactive");
+
+               if ($num_inactive > 0) {
+                       $inactive_button = "<button dojoType=\"dijit.form.Button\"
+                                       onclick=\"showInactiveFeeds()\">" .
+                                       __("Inactive feeds") . "</button>";
+               }
+
+               $feed_search = db_escape_string($_REQUEST["search"]);
+
+               if (array_key_exists("search", $_REQUEST)) {
+                       $_SESSION["prefs_feed_search"] = $feed_search;
+               } else {
+                       $feed_search = $_SESSION["prefs_feed_search"];
+               }
+
+               print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
+
+               print "<div region='top' dojoType=\"dijit.Toolbar\">"; #toolbar
+
+               print "<div style='float : right; padding-right : 4px;'>
+                       <input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"
+                               value=\"$feed_search\">
+                       <button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">".
+                               __('Search')."</button>
+                       </div>";
+
+               print "<div dojoType=\"dijit.form.DropDownButton\">".
+                               "<span>" . __('Select')."</span>";
+               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
+               print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"
+                       dojoType=\"dijit.MenuItem\">".__('All')."</div>";
+               print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"
+                       dojoType=\"dijit.MenuItem\">".__('None')."</div>";
+               print "</div></div>";
+
+               print "<div dojoType=\"dijit.form.DropDownButton\">".
+                               "<span>" . __('Feeds')."</span>";
+               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
+               print "<div onclick=\"quickAddFeed()\"
+                       dojoType=\"dijit.MenuItem\">".__('Subscribe to feed')."</div>";
+               print "<div onclick=\"editSelectedFeed()\"
+                       dojoType=\"dijit.MenuItem\">".__('Edit selected feeds')."</div>";
+               print "<div onclick=\"resetFeedOrder()\"
+                       dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
+               print "<div onclick=\"batchSubscribe()\"
+                       dojoType=\"dijit.MenuItem\">".__('Batch subscribe')."</div>";
+               print "</div></div>";
+
+               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
+                       print "<div dojoType=\"dijit.form.DropDownButton\">".
+                                       "<span>" . __('Categories')."</span>";
+                       print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
+                       print "<div onclick=\"createCategory()\"
+                               dojoType=\"dijit.MenuItem\">".__('Add category')."</div>";
+                       print "<div onclick=\"toggleHiddenFeedCats()\"
+                               dojoType=\"dijit.MenuItem\">".__('(Un)hide empty categories')."</div>";
+                       print "<div onclick=\"resetCatOrder()\"
+                               dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
+                       print "</div></div>";
+
+               }
+
+               print $error_button;
+               print $inactive_button;
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedFeeds()\">"
+                       .__('Unsubscribe')."</button dojoType=\"dijit.form.Button\"> ";
+
+               if (defined('_ENABLE_FEED_DEBUGGING')) {
+
+                       print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">
+                               <option value=\"facDefault\" selected>".__('More actions...')."</option>";
+
+                       if (FORCE_ARTICLE_PURGE == 0) {
+                               print
+                                       "<option value=\"facPurge\">".__('Manual purge')."</option>";
+                       }
+
+                       print "
+                               <option value=\"facClear\">".__('Clear feed data')."</option>
+                               <option value=\"facRescore\">".__('Rescore articles')."</option>";
+
+                       print "</select>";
+
+               }
+
+               print "</div>"; # toolbar
+
+               //print '</div>';
+               print '<div dojoType="dijit.layout.ContentPane" region="center">';
+
+               print "<div id=\"feedlistLoading\">
+               <img src='images/indicator_tiny.gif'>".
+                __("Loading, please wait...")."</div>";
+
+               print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"
+                       url=\"backend.php?op=pref-feeds&method=getfeedtree\">
+               </div>
+               <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"
+               query=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"
+                       childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
+               </div>
+               <div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"
+                       dndController=\"dijit.tree.dndSource\"
+                       betweenThreshold=\"5\"
+                       model=\"feedModel\" openOnClick=\"false\">
+               <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
+                       var id = String(item.id);
+                       var bare_id = id.substr(id.indexOf(':')+1);
+
+                       if (id.match('FEED:')) {
+                               editFeed(bare_id);
+                       } else if (id.match('CAT:')) {
+                               editCat(bare_id, item);
+                       }
+               </script>
+               <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
+                       Element.hide(\"feedlistLoading\");
+               </script>
+               </div>";
+
+#              print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">
+#                      ".__('<b>Hint:</b> you can drag feeds and categories around.')."
+#                      </div>";
+
+               print '</div>';
+               print '</div>';
+
+               print "</div>"; # feeds pane
+
+               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Import and export')."\">";
+
+               print "<h3>" . __("OPML") . "</h3>";
+
+               print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . " ";
+
+               print __("Only main settings profile can be migrated using OPML.") . "</p>";
+
+               print "<iframe id=\"upload_iframe\"
+                       name=\"upload_iframe\" onload=\"opmlImportComplete(this)\"
+                       style=\"width: 400px; height: 100px; display: none;\"></iframe>";
+
+               print "<form  name=\"opml_form\" style='display : block' target=\"upload_iframe\"
+                       enctype=\"multipart/form-data\" method=\"POST\"
+                       action=\"backend.php\">
+                       <input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;
+                       <input type=\"hidden\" name=\"op\" value=\"dlg\">
+                       <input type=\"hidden\" name=\"method\" value=\"importOpml\">
+                       <button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" .
+                       __('Import my OPML') . "</button>";
+
+               print "<hr>";
+
+               print "<p>" . __('Filename:') .
+            " <input type=\"text\" id=\"filename\" value=\"TinyTinyRSS.opml\" />&nbsp;" .
+                               __('Include settings') . "<input type=\"checkbox\" id=\"settings\" checked=\"1\"/>";
+
+               print "</p><button dojoType=\"dijit.form.Button\"
+                       onclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" .
+              __('Export OPML') . "</button></p></form>";
+
+               print "<hr>";
+
+               print "<p>".__('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . " ";
+
+               print __("Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.") . "</p>";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('pubOPMLUrl')\">".
+                       __('Display published OPML URL')."</button> ";
+
+
+               print "<h3>" . __("Article archive") . "</h3>";
+
+               print "<p>" . __("You can export and import your Starred and Archived articles for safekeeping or when migrating between tt-rss instances.") . "</p>";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return exportData()\">".
+                       __('Export my data')."</button> ";
+
+               print "<hr>";
+
+               print "<iframe id=\"data_upload_iframe\"
+                       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\">&nbsp;
+                       <input type=\"hidden\" name=\"op\" value=\"dlg\">
+                       <input type=\"hidden\" name=\"method\" value=\"dataimport\">
+                       <button dojoType=\"dijit.form.Button\" onclick=\"return importData();\" type=\"submit\">" .
+                       __('Import') . "</button>";
+
+
+               print "</div>"; # pane
+
+               if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
+
+                       print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Firefox integration')."\">";
+
+                       print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>";
+
+                       print "<p>";
+
+                       print "<button onclick='window.navigator.registerContentHandler(" .
+                      "\"application/vnd.mozilla.maybe.feed\", " .
+                      "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" .
+                                                        __('Click here to register this site as a feed reader.') .
+                               "</button>";
+
+                       print "</p>";
+
+                       print "</div>"; # pane
+               }
+
+               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Subscribing using bookmarklet')."\">";
+
+               print "<p>" . __("Drag the link below to your browser toolbar, open the feed you're interested in in your browser and click on the link to subscribe to it.") . "</p>";
+
+               $bm_subscribe_url = str_replace('%s', '', add_feed_url());
+
+               $confirm_str = str_replace("'", "\'", __('Subscribe to %s in Tiny Tiny RSS?'));
+
+               $bm_url = htmlspecialchars("javascript:{if(confirm('$confirm_str'.replace('%s',window.location.href)))window.location.href='$bm_subscribe_url'+window.location.href}");
+
+               print "<a href=\"$bm_url\" class='bookmarklet'>" . __('Subscribe in Tiny Tiny RSS'). "</a>";
+
+               print "</div>"; #pane
+
+               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Published & shared articles / Generated feeds')."\">";
+
+               print "<h3>" . __("Published articles and generated feeds") . "</h3>";
+
+               print "<p>".__('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.')."</p>";
+
+               $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() .
+                               "/public.php?op=rss&id=-2&view-mode=all_articles");;
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('generatedFeed', '$rss_url')\">".
+                       __('Display URL')."</button> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">".
+                       __('Clear all generated URLs')."</button> ";
+
+               print "<h3>" . __("Articles shared by URL") . "</h3>";
+
+               print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">".
+                       __('Unshare all articles')."</button> ";
+
+               print "</div>"; #pane
+
+               if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
+
+                       print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Twitter')."\">";
+
+                       $result = db_query($this->link, "SELECT COUNT(*) AS cid FROM ttrss_users
+                               WHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND
+                               id = " . $_SESSION['uid']);
+
+                       $is_registered = db_fetch_result($result, 0, "cid") != 0;
+
+                       if (!$is_registered) {
+                               print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
+                       } else {
+                               print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
+                       }
+
+                       print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">".
+                               __("Register with Twitter.com")."</button>";
+
+                       print " ";
+
+                       print "<button dojoType=\"dijit.form.Button\"
+                               onclick=\"return clearTwitterCredentials()\">".
+                               __("Clear stored credentials")."</button>";
+
+                       print "</div>"; # pane
+
+               }
+
+               print "</div>"; #container
+
+       }
+
+       private function feedlist_init_cat($cat_id, $hidden = false) {
+               $obj = array();
+               $cat_id = (int) $cat_id;
+
+               if ($cat_id > 0) {
+                       $cat_unread = ccache_find($this->link, $cat_id, $_SESSION["uid"], true);
+               } else if ($cat_id == 0 || $cat_id == -2) {
+                       $cat_unread = getCategoryUnread($this->link, $cat_id);
+               }
+
+               $obj['id'] = 'CAT:' . $cat_id;
+               $obj['items'] = array();
+               $obj['name'] = getCategoryTitle($this->link, $cat_id);
+               $obj['type'] = 'category';
+               $obj['unread'] = (int) $cat_unread;
+               $obj['hidden'] = $hidden;
+               $obj['bare_id'] = $cat_id;
+
+               return $obj;
+       }
+
+       private function feedlist_init_feed($feed_id, $title = false, $unread = false, $error = '', $updated = '') {
+               $obj = array();
+               $feed_id = (int) $feed_id;
+
+               if (!$title)
+                       $title = getFeedTitle($this->link, $feed_id, false);
+
+               if ($unread === false)
+                       $unread = getFeedUnread($this->link, $feed_id, false);
+
+               $obj['id'] = 'FEED:' . $feed_id;
+               $obj['name'] = $title;
+               $obj['unread'] = (int) $unread;
+               $obj['type'] = 'feed';
+               $obj['error'] = $error;
+               $obj['updated'] = $updated;
+               $obj['icon'] = getFeedIcon($feed_id);
+               $obj['bare_id'] = $feed_id;
+
+               return $obj;
+       }
+
+}
+?>
diff --git a/classes/pref/filters.php b/classes/pref/filters.php
new file mode 100644 (file)
index 0000000..9cd59e9
--- /dev/null
@@ -0,0 +1,657 @@
+<?php
+class Pref_Filters extends Handler_Protected {
+
+       function csrf_ignore($method) {
+               $csrf_ignored = array("index", "getfiltertree", "edit");
+
+               return array_search($method, $csrf_ignored) !== false;
+       }
+
+       function filter_test($filter_type, $reg_exp,
+                       $action_id, $action_param, $filter_param, $inverse, $feed_id, $cat_id,
+                       $cat_filter) {
+
+               $result = db_query($this->link, "SELECT name FROM ttrss_filter_types WHERE
+                       id = " . $filter_type);
+               $type_name = db_fetch_result($result, 0, "name");
+
+               $result = db_query($this->link, "SELECT name FROM ttrss_filter_actions WHERE
+                       id = " . $action_id);
+               $action_name = db_fetch_result($result, 0, "name");
+
+               $filter["reg_exp"] = $reg_exp;
+               $filter["action"] = $action_name;
+               $filter["type"] = $type_name;
+               $filter["action_param"] = $action_param;
+               $filter["filter_param"] = $filter_param;
+               $filter["inverse"] = $inverse;
+
+               $filters[$type_name] = array($filter);
+
+               if ($feed_id)
+                       $feed = $feed_id;
+               else
+                       $feed = -4;
+
+               $regexp_valid = preg_match('/' . $filter['reg_exp'] . '/',
+                       $filter['reg_exp']) !== FALSE;
+
+               print __("Articles matching this filter:");
+
+               print "<div class=\"filterTestHolder\">";
+               print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
+
+               if ($regexp_valid) {
+
+                       $feed_title = getFeedTitle($this->link, $feed);
+
+                       $qfh_ret = queryFeedHeadlines($this->link, $cat_filter ? $cat_id : $feed,
+                               30, "", $cat_filter, false, false,
+                               false, "date_entered DESC", 0, $_SESSION["uid"], $filter);
+
+                       $result = $qfh_ret[0];
+
+                       $articles = array();
+                       $found = 0;
+
+                       while ($line = db_fetch_assoc($result)) {
+
+                               $entry_timestamp = strtotime($line["updated"]);
+                               $entry_tags = get_article_tags($this->link, $line["id"], $_SESSION["uid"]);
+
+                               $content_preview = truncate_string(
+                                       strip_tags($line["content_preview"]), 100, '...');
+
+                               if ($line["feed_title"])
+                                       $feed_title = $line["feed_title"];
+
+                               print "<tr>";
+
+                               print "<td width='5%' align='center'><input
+                                       dojoType=\"dijit.form.CheckBox\" checked=\"1\"
+                                       disabled=\"1\" type=\"checkbox\"></td>";
+                               print "<td>";
+
+                               print $line["title"];
+                               print "&nbsp;(";
+                               print "<b>" . $feed_title . "</b>";
+                               print "):&nbsp;";
+                               print "<span class=\"insensitive\">" . $content_preview . "</span>";
+                               print " " . mb_substr($line["date_entered"], 0, 16);
+
+                               print "</td></tr>";
+
+                               $found++;
+                       }
+
+                       if ($found == 0) {
+                               print "<tr><td align='center'>" .
+                                       __("No articles matching this filter has been found.") . "</td></tr>";
+                       }
+               } else {
+                       print "<tr><td align='center' class='error'>" .
+                               __("Invalid regular expression.") . "</td></tr>";
+
+               }
+
+               print "</table>";
+               print "</div>";
+
+       }
+
+       function getfiltertree() {
+               $root = array();
+               $root['id'] = 'root';
+               $root['name'] = __('Filters');
+               $root['items'] = array();
+
+               $search = $_SESSION["prefs_filter_search"];
+
+               if ($search) $search_qpart = " (LOWER(reg_exp) LIKE LOWER('%$search%')
+                       OR LOWER(ttrss_feeds.title) LIKE LOWER('%$search%')
+                       OR LOWER(COALESCE(ttrss_feed_categories.title, '".__('Uncategorized')."'))
+                               LIKE LOWER('%$search%') AND cat_filter = true) AND ";
+
+               $result = db_query($this->link, "SELECT
+                               ttrss_filters.id AS id,reg_exp,
+                               ttrss_filter_types.name AS filter_type_name,
+                               ttrss_filter_types.description AS filter_type_descr,
+                               enabled,
+                               inverse,
+                               cat_filter,
+                               feed_id,
+                               ttrss_filters.cat_id,
+                               action_id,
+                               filter_param,
+                               filter_type,
+                               ttrss_filter_actions.description AS action_description,
+                               ttrss_feeds.title AS feed_title,
+                               COALESCE(ttrss_feed_categories.title, '".__('Uncategorized')."') AS cat_title,
+                               ttrss_filter_actions.name AS action_name,
+                               ttrss_filters.action_param AS action_param
+                       FROM
+                               ttrss_filter_types,ttrss_filter_actions,ttrss_filters LEFT JOIN
+                                       ttrss_feeds ON (ttrss_filters.feed_id = ttrss_feeds.id) LEFT JOIN
+                                       ttrss_feed_categories ON (ttrss_filters.cat_id = ttrss_feed_categories.id)
+                       WHERE
+                               filter_type = ttrss_filter_types.id AND
+                               ttrss_filter_actions.id = action_id AND
+                               $search_qpart
+                               ttrss_filters.owner_uid = ".$_SESSION["uid"]."
+                       ORDER by action_description, reg_exp");
+
+               $cat = false;
+               $cur_action_description = "";
+
+               if (db_num_rows($result) > 0) {
+
+                       while ($line = db_fetch_assoc($result)) {
+                               if ($cur_action_description != $line['action_description']) {
+
+                                       if ($cat)
+                                               array_push($root['items'], $cat);
+
+                                       $cat = array();
+                                       $cat['id'] = 'ACTION:' . $line['action_id'];
+                                       $cat['name'] = $line['action_description'];
+                                       $cat['items'] = array();
+
+                                       $cur_action_description = $line['action_description'];
+                               }
+
+                               if (array_search($line["action_name"],
+                                       array("score", "tag", "label")) === false) {
+
+                                               $line["action_param"] = '';
+                               } else {
+                                       if ($line['action_name'] == 'label') {
+
+                                               $tmp_result = db_query($this->link, "SELECT fg_color, bg_color
+                                                       FROM ttrss_labels2 WHERE caption = '".
+                                                               db_escape_string($line["action_param"])."' AND
+                                                               owner_uid = " . $_SESSION["uid"]);
+
+                                               if (db_num_rows($tmp_result) != 0) {
+                                                       $fg_color = db_fetch_result($tmp_result, 0, "fg_color");
+                                                       $bg_color = db_fetch_result($tmp_result, 0, "bg_color");
+
+                                                       $tmp = "<span class=\"labelColorIndicator\" style='color : $fg_color; background-color : $bg_color'>&alpha;</span> " . $line['action_param'];
+
+                                                       $line['action_param'] = $tmp;
+                                               }
+                                       }
+                               }
+
+                               $filter = array();
+                               $filter['id'] = 'FILTER:' . $line['id'];
+                               $filter['bare_id'] = $line['id'];
+                               $filter['name'] = $line['reg_exp'];
+                               $filter['type'] = $line['filter_type'];
+                               $filter['enabled'] = sql_bool_to_bool($line['enabled']);
+                               $filter['param'] = $line['action_param'];
+                               $filter['inverse'] = sql_bool_to_bool($line['inverse']);
+                               $filter['checkbox'] = false;
+
+                               if (sql_bool_to_bool($line['cat_filter']))
+                                       if ($line['cat_id'] != 0) {
+                                               $filter['feed'] = $line['cat_title'];
+                                       } else {
+                                               $filter['feed'] = __('Uncategorized');
+                                       }
+                               else if ($line['feed_id'])
+                                       $filter['feed'] = $line['feed_title'];
+
+                               array_push($cat['items'], $filter);
+                       }
+
+                       array_push($root['items'], $cat);
+               }
+
+               $fl = array();
+               $fl['identifier'] = 'id';
+               $fl['label'] = 'name';
+               $fl['items'] = array($root);
+
+               print json_encode($fl);
+               return;
+       }
+
+       function edit() {
+
+               $filter_id = db_escape_string($_REQUEST["id"]);
+
+               $result = db_query($this->link,
+                       "SELECT * FROM ttrss_filters WHERE id = '$filter_id' AND owner_uid = " . $_SESSION["uid"]);
+
+               $reg_exp = htmlspecialchars(db_fetch_result($result, 0, "reg_exp"));
+               $filter_type = db_fetch_result($result, 0, "filter_type");
+               $feed_id = db_fetch_result($result, 0, "feed_id");
+               $cat_id = db_fetch_result($result, 0, "cat_id");
+               $action_id = db_fetch_result($result, 0, "action_id");
+               $action_param = db_fetch_result($result, 0, "action_param");
+               $filter_param = db_fetch_result($result, 0, "filter_param");
+
+               $enabled = sql_bool_to_bool(db_fetch_result($result, 0, "enabled"));
+               $inverse = sql_bool_to_bool(db_fetch_result($result, 0, "inverse"));
+               $cat_filter = sql_bool_to_bool(db_fetch_result($result, 0, "cat_filter"));
+
+               print "<form id=\"filter_edit_form\" onsubmit='return false'>";
+
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-filters\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$filter_id\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"editSave\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"csrf_token\" value=\"".$_SESSION['csrf_token']."\">";
+
+               $result = db_query($this->link, "SELECT id,description
+                       FROM ttrss_filter_types ORDER BY description");
+
+               $filter_types = array();
+
+               while ($line = db_fetch_assoc($result)) {
+                       //array_push($filter_types, $line["description"]);
+                       $filter_types[$line["id"]] = __($line["description"]);
+               }
+
+               print "<div class=\"dlgSec\">".__("Match")."</div>";
+
+               print "<div class=\"dlgSecCont\">";
+
+               if ($filter_type != 5) {
+                       $date_ops_invisible = 'style="display : none"';
+               }
+
+               print "<span id=\"filterDlg_dateModBox\" $date_ops_invisible>";
+               print __("Date") . " ";
+
+               $filter_params = array(
+                       "before" => __("before"),
+                       "after" => __("after"));
+
+               print_select_hash("filter_date_modifier", $filter_param,
+                       $filter_params, 'dojoType="dijit.form.Select"');
+
+               print "&nbsp;</span>";
+
+               print "<input dojoType=\"dijit.form.ValidationTextBox\"
+                                required=\"1\"
+                                name=\"reg_exp\" style=\"font-size : 16px;\" value=\"$reg_exp\">";
+
+               print "<span id=\"filterDlg_dateChkBox\" $date_ops_invisible>";
+               print "&nbsp;<button dojoType=\"dijit.form.Button\" onclick=\"return filterDlgCheckDate()\">".
+                       __('Check it')."</button>";
+               print "</span>";
+
+               print "<hr/> " . __("on field") . " ";
+               print_select_hash("filter_type", $filter_type, $filter_types,
+                       'onchange="filterDlgCheckType(this)" dojoType="dijit.form.Select"');
+
+               print "<hr/>";
+
+               print __("in") . " ";
+
+               $hidden = $cat_filter ? "style='display:none'" : "";
+
+               print "<span id='filterDlg_feeds' $hidden>";
+               print_feed_select($this->link, "feed_id", $feed_id,
+                       'dojoType="dijit.form.FilteringSelect"');
+               print "</span>";
+
+               $hidden = $cat_filter ? "" : "style='display:none'";
+
+               print "<span id='filterDlg_cats' $hidden>";
+               print_feed_cat_select($this->link, "cat_id", $cat_id,
+                       'dojoType="dijit.form.FilteringSelect"');
+               print "</span>";
+
+
+               print "</div>";
+
+               print "<div class=\"dlgSec\">".__("Perform Action")."</div>";
+
+               print "<div class=\"dlgSecCont\">";
+
+               print "<select name=\"action_id\" dojoType=\"dijit.form.Select\"
+                       onchange=\"filterDlgCheckAction(this)\">";
+
+               $result = db_query($this->link, "SELECT id,description FROM ttrss_filter_actions
+                       ORDER BY name");
+
+               while ($line = db_fetch_assoc($result)) {
+                       $is_sel = ($line["id"] == $action_id) ? "selected=\"1\"" : "";
+                       printf("<option value='%d' $is_sel>%s</option>", $line["id"], __($line["description"]));
+               }
+
+               print "</select>";
+
+               $param_hidden = ($action_id == 4 || $action_id == 6 || $action_id == 7) ? "" : "display : none";
+
+               print "<span id=\"filterDlg_paramBox\" style=\"$param_hidden\">";
+               print " " . __("with parameters:") . " ";
+
+               $param_int_hidden = ($action_id != 7) ? "" : "display : none";
+
+               print "<input style=\"$param_int_hidden\"
+                               dojoType=\"dijit.form.TextBox\" id=\"filterDlg_actionParam\"
+                               name=\"action_param\" value=\"$action_param\">";
+
+               $param_int_hidden = ($action_id == 7) ? "" : "display : none";
+
+               print_label_select($this->link, "action_param_label", $action_param,
+                "style=\"$param_int_hidden\"" .
+                'id="filterDlg_actionParamLabel" dojoType="dijit.form.Select"');
+
+               print "</span>";
+
+               print "&nbsp;"; // tiny layout hack
+
+               print "</div>";
+
+               print "<div class=\"dlgSec\">".__("Options")."</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               print "<div style=\"line-height : 100%\">";
+
+               if ($enabled) {
+                       $checked = "checked=\"1\"";
+               } else {
+                       $checked = "";
+               }
+
+               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"enabled\" id=\"enabled\" $checked>
+                               <label for=\"enabled\">".__('Enabled')."</label><hr/>";
+
+               if ($inverse) {
+                       $checked = "checked=\"1\"";
+               } else {
+                       $checked = "";
+               }
+
+               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"inverse\" id=\"inverse\" $checked>
+                       <label for=\"inverse\">".__('Inverse match')."</label><hr/>";
+
+               if ($cat_filter) {
+                       $checked = "checked=\"1\"";
+               } else {
+                       $checked = "";
+               }
+
+               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"cat_filter\" id=\"cat_filter\" onchange=\"filterDlgCheckCat(this)\" $checked>
+                               <label for=\"cat_filter\">".__('Apply to category')."</label><hr/>";
+
+               print "</div>";
+               print "</div>";
+
+               print "<div class=\"dlgButtons\">";
+
+               print "<div style=\"float : left\">";
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').removeFilter()\">".
+                       __('Remove')."</button>";
+               print "</div>";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').test()\">".
+                       __('Test')."</button> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').execute()\">".
+                       __('Save')."</button> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').hide()\">".
+                       __('Cancel')."</button>";
+
+               print "</div>";
+       }
+
+       function editSave() {
+
+               $savemode = db_escape_string($_REQUEST["savemode"]);
+               $reg_exp = db_escape_string(trim($_REQUEST["reg_exp"]));
+               $filter_type = db_escape_string(trim($_REQUEST["filter_type"]));
+               $filter_id = db_escape_string($_REQUEST["id"]);
+               $feed_id = db_escape_string($_REQUEST["feed_id"]);
+               $action_id = db_escape_string($_REQUEST["action_id"]);
+               $action_param = db_escape_string($_REQUEST["action_param"]);
+               $action_param_label = db_escape_string($_REQUEST["action_param_label"]);
+               $enabled = checkbox_to_sql_bool(db_escape_string($_REQUEST["enabled"]));
+               $inverse = checkbox_to_sql_bool(db_escape_string($_REQUEST["inverse"]));
+               $cat_filter = checkbox_to_sql_bool(db_escape_string($_REQUEST["cat_filter"]));
+               $cat_id = db_escape_string($_REQUEST['cat_id']);
+
+               # for the time being, no other filters use params anyway...
+               $filter_param = db_escape_string($_REQUEST["filter_date_modifier"]);
+
+               if (!$feed_id) {
+                       $feed_id = 'NULL';
+               } else {
+                       $feed_id = sprintf("'%s'", db_escape_string($feed_id));
+               }
+
+               if (!$cat_id) {
+                       $cat_id = 'NULL';
+               } else {
+                       $cat_id = sprintf("'%d'", db_escape_string($cat_id));
+               }
+
+               /* When processing 'assign label' filters, action_param_label dropbox
+                * overrides action_param */
+
+               if ($action_id == 7) {
+                       $action_param = $action_param_label;
+               }
+
+               if ($action_id == 6) {
+                       $action_param = (int) str_replace("+", "", $action_param);
+               }
+
+               if ($savemode != "test") {
+                       $result = db_query($this->link, "UPDATE ttrss_filters SET
+                               reg_exp = '$reg_exp',
+                               feed_id = $feed_id,
+                               cat_id = $cat_id,
+                               action_id = '$action_id',
+                               filter_type = '$filter_type',
+                               enabled = $enabled,
+                               inverse = $inverse,
+                               cat_filter = $cat_filter,
+                               action_param = '$action_param',
+                               filter_param = '$filter_param'
+                               WHERE id = '$filter_id' AND owner_uid = " . $_SESSION["uid"]);
+               } else {
+
+                       $this->filter_test($filter_type, $reg_exp,
+                               $action_id, $action_param, $filter_param, sql_bool_to_bool($inverse),
+                               (int) $_REQUEST["feed_id"], (int) $_REQUEST['cat_id'],
+                               sql_bool_to_bool($cat_filter));
+
+                       print "<div align='center'>";
+                       print "<button dojoType=\"dijit.form.Button\"
+                               onclick=\"return dijit.byId('filterTestDlg').hide()\">".
+                               __('Close this window')."</button>";
+                       print "</div>";
+
+               }
+       }
+
+       function remove() {
+
+               $ids = split(",", db_escape_string($_REQUEST["ids"]));
+
+               foreach ($ids as $id) {
+                       db_query($this->link, "DELETE FROM ttrss_filters WHERE id = '$id' AND owner_uid = ". $_SESSION["uid"]);
+               }
+       }
+
+       function add() {
+
+               $savemode = db_escape_string($_REQUEST["savemode"]);
+               $regexp = db_escape_string(trim($_REQUEST["reg_exp"]));
+               $filter_type = db_escape_string(trim($_REQUEST["filter_type"]));
+               $feed_id = db_escape_string($_REQUEST["feed_id"]);
+               $cat_id = db_escape_string($_REQUEST["cat_id"]);
+               $action_id = db_escape_string($_REQUEST["action_id"]);
+               $action_param = db_escape_string($_REQUEST["action_param"]);
+               $action_param_label = db_escape_string($_REQUEST["action_param_label"]);
+               $inverse = checkbox_to_sql_bool(db_escape_string($_REQUEST["inverse"]));
+               $cat_filter = checkbox_to_sql_bool(db_escape_string($_REQUEST["cat_filter"]));
+
+               # for the time being, no other filters use params anyway...
+               $filter_param = db_escape_string($_REQUEST["filter_date_modifier"]);
+
+               if (!$regexp) return;
+
+               if (!$feed_id) {
+                       $feed_id = 'NULL';
+               } else {
+                       $feed_id = sprintf("'%s'", db_escape_string($feed_id));
+               }
+
+               if (!$cat_id) {
+                       $cat_id = 'NULL';
+               } else {
+                       $cat_id = sprintf("'%d'", db_escape_string($cat_id));
+               }
+
+               /* When processing 'assign label' filters, action_param_label dropbox
+                * overrides action_param */
+
+               if ($action_id == 7) {
+                       $action_param = $action_param_label;
+               }
+
+               if ($action_id == 6) {
+                       $action_param = (int) str_replace("+", "", $action_param);
+               }
+
+               if ($savemode != "test") {
+                       $result = db_query($this->link,
+                               "INSERT INTO ttrss_filters (reg_exp,filter_type,owner_uid,feed_id,
+                                       action_id, action_param, inverse, filter_param, cat_id, cat_filter)
+                               VALUES
+                                       ('$regexp', '$filter_type','".$_SESSION["uid"]."',
+                                       $feed_id, '$action_id', '$action_param', $inverse,
+                                       '$filter_param', $cat_id, $cat_filter)");
+
+                       if (db_affected_rows($this->link, $result) != 0) {
+                               print T_sprintf("Created filter <b>%s</b>", htmlspecialchars($regexp));
+                       }
+
+               } else {
+
+                       $this->filter_test($filter_type, $regexp,
+                               $action_id, $action_param, $filter_param, sql_bool_to_bool($inverse),
+                               (int) $_REQUEST["feed_id"], (int) $_REQUEST['cat_id'],
+                               sql_bool_to_bool($cat_filter));
+
+                       print "<div align='center'>";
+                       print "<button dojoType=\"dijit.form.Button\"
+                               onclick=\"return dijit.byId('filterTestDlg').hide()\">".
+                               __('Close this window')."</button>";
+                       print "</div>";
+
+               }
+       }
+
+       function index() {
+
+               $sort = db_escape_string($_REQUEST["sort"]);
+
+               if (!$sort || $sort == "undefined") {
+                       $sort = "reg_exp";
+               }
+
+               $result = db_query($this->link, "SELECT id,description
+                       FROM ttrss_filter_types ORDER BY description");
+
+               $filter_types = array();
+
+               while ($line = db_fetch_assoc($result)) {
+                       //array_push($filter_types, $line["description"]);
+                       $filter_types[$line["id"]] = $line["description"];
+               }
+
+
+               $filter_search = db_escape_string($_REQUEST["search"]);
+
+               if (array_key_exists("search", $_REQUEST)) {
+                       $_SESSION["prefs_filter_search"] = $filter_search;
+               } else {
+                       $filter_search = $_SESSION["prefs_filter_search"];
+               }
+
+               print "<div id=\"pref-filter-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
+               print "<div id=\"pref-filter-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
+               print "<div id=\"pref-filter-toolbar\" dojoType=\"dijit.Toolbar\">";
+
+               $filter_search = db_escape_string($_REQUEST["search"]);
+
+               if (array_key_exists("search", $_REQUEST)) {
+                       $_SESSION["prefs_filter_search"] = $filter_search;
+               } else {
+                       $filter_search = $_SESSION["prefs_filter_search"];
+               }
+
+               print "<div style='float : right; padding-right : 4px;'>
+                       <input dojoType=\"dijit.form.TextBox\" id=\"filter_search\" size=\"20\" type=\"search\"
+                               value=\"$filter_search\">
+                       <button dojoType=\"dijit.form.Button\" onclick=\"updateFilterList()\">".
+                               __('Search')."</button>
+                       </div>";
+
+               print "<div dojoType=\"dijit.form.DropDownButton\">".
+                               "<span>" . __('Select')."</span>";
+               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
+               print "<div onclick=\"dijit.byId('filterTree').model.setAllChecked(true)\"
+                       dojoType=\"dijit.MenuItem\">".__('All')."</div>";
+               print "<div onclick=\"dijit.byId('filterTree').model.setAllChecked(false)\"
+                       dojoType=\"dijit.MenuItem\">".__('None')."</div>";
+               print "</div></div>";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return quickAddFilter()\">".
+                       __('Create filter')."</button> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return editSelectedFilter()\">".
+                       __('Edit')."</button> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return removeSelectedFilters()\">".
+                       __('Remove')."</button> ";
+
+               if (defined('_ENABLE_FEED_DEBUGGING')) {
+                       print "<button dojoType=\"dijit.form.Button\" onclick=\"rescore_all_feeds()\">".
+                               __('Rescore articles')."</button> ";
+               }
+
+               print "</div>"; # toolbar
+               print "</div>"; # toolbar-frame
+               print "<div id=\"pref-filter-content\" dojoType=\"dijit.layout.ContentPane\" region=\"center\">";
+
+               print "<div id=\"filterlistLoading\">
+               <img src='images/indicator_tiny.gif'>".
+                __("Loading, please wait...")."</div>";
+
+               print "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"filterStore\"
+                       url=\"backend.php?op=pref-filters&method=getfiltertree\">
+               </div>
+               <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"filterModel\" store=\"filterStore\"
+               query=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"
+                       childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
+               </div>
+               <div dojoType=\"fox.PrefFilterTree\" id=\"filterTree\"
+                       model=\"filterModel\" openOnClick=\"true\">
+               <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
+                       Element.hide(\"filterlistLoading\");
+               </script>
+               <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
+                       var id = String(item.id);
+                       var bare_id = id.substr(id.indexOf(':')+1);
+
+                       if (id.match('FILTER:')) {
+                               editFilter(bare_id);
+                       }
+               </script>
+
+               </div>";
+
+               print "</div>"; #pane
+               print "</div>"; #container
+
+       }
+}
+?>
diff --git a/classes/pref/instances.php b/classes/pref/instances.php
new file mode 100644 (file)
index 0000000..c017ee9
--- /dev/null
@@ -0,0 +1,210 @@
+<?php
+class Pref_Instances extends Handler_Protected {
+
+       function csrf_ignore($method) {
+               $csrf_ignored = array("index", "edit");
+
+               return array_search($method, $csrf_ignored) !== false;
+       }
+
+       function before($method) {
+               if (parent::before($method)) {
+                       if ($_SESSION["access_level"] < 10) {
+                               print __("Your access level is insufficient to open this tab.");
+                               return false;
+                       }
+                       return true;
+               }
+               return false;
+       }
+
+       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%\">&nbsp;</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('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>" . htmlspecialchars($line['num_feeds']) . "</td>";
+
+                       print "</tr>";
+
+                       ++$lnum;
+               }
+
+               print "</table>";
+
+               print "</div>"; #pane
+               print "</div>"; #container
+
+       }
+}
+?>
diff --git a/classes/pref/labels.php b/classes/pref/labels.php
new file mode 100644 (file)
index 0000000..317f927
--- /dev/null
@@ -0,0 +1,326 @@
+<?php
+class Pref_Labels extends Handler_Protected {
+
+       function csrf_ignore($method) {
+               $csrf_ignored = array("index", "getlabeltree", "edit");
+
+               return array_search($method, $csrf_ignored) !== false;
+       }
+
+       function edit() {
+               $label_id = db_escape_string($_REQUEST['id']);
+
+               $result = db_query($this->link, "SELECT * FROM ttrss_labels2 WHERE
+                       id = '$label_id' AND owner_uid = " . $_SESSION["uid"]);
+
+               $line = db_fetch_assoc($result);
+
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$label_id\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-labels\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"save\">";
+
+               print "<div class=\"dlgSec\">".__("Caption")."</div>";
+
+               print "<div class=\"dlgSecCont\">";
+
+               $fg_color = $line['fg_color'];
+               $bg_color = $line['bg_color'];
+
+               print "<span class=\"labelColorIndicator\" id=\"label-editor-indicator\" style='color : $fg_color; background-color : $bg_color; margin-bottom : 4px; margin-right : 4px'>&alpha;</span>";
+
+               print "<input style=\"font-size : 16px\" name=\"caption\"
+                       dojoType=\"dijit.form.ValidationTextBox\"
+                       required=\"true\"
+                       value=\"".htmlspecialchars($line['caption'])."\">";
+
+               print "</div>";
+               print "<div class=\"dlgSec\">" . __("Colors") . "</div>";
+               print "<div class=\"dlgSecCont\">";
+
+               print "<table cellspacing=\"0\">";
+
+               print "<tr><td>".__("Foreground:")."</td><td>".__("Background:").
+                       "</td></tr>";
+
+               print "<tr><td style='padding-right : 10px'>";
+
+               print "<input dojoType=\"dijit.form.TextBox\"
+                       style=\"display : none\" id=\"labelEdit_fgColor\"
+                       name=\"fg_color\" value=\"$fg_color\">";
+               print "<input dojoType=\"dijit.form.TextBox\"
+                       style=\"display : none\" id=\"labelEdit_bgColor\"
+                       name=\"bg_color\" value=\"$bg_color\">";
+
+               print "<div dojoType=\"dijit.ColorPalette\">
+                       <script type=\"dojo/method\" event=\"onChange\" args=\"fg_color\">
+                               dijit.byId(\"labelEdit_fgColor\").attr('value', fg_color);
+                               $('label-editor-indicator').setStyle({color: fg_color});
+                       </script>
+               </div>";
+               print "</div>";
+
+               print "</td><td>";
+
+               print "<div dojoType=\"dijit.ColorPalette\">
+                       <script type=\"dojo/method\" event=\"onChange\" args=\"bg_color\">
+                               dijit.byId(\"labelEdit_bgColor\").attr('value', bg_color);
+                               $('label-editor-indicator').setStyle({backgroundColor: bg_color});
+                       </script>
+               </div>";
+               print "</div>";
+
+               print "</td></tr></table>";
+               print "</div>";
+
+#                      print "</form>";
+
+               print "<div class=\"dlgButtons\">";
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('labelEditDlg').execute()\">".
+                       __('Save')."</button>";
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('labelEditDlg').hide()\">".
+                       __('Cancel')."</button>";
+               print "</div>";
+
+               return;
+       }
+
+       function getlabeltree() {
+               $root = array();
+               $root['id'] = 'root';
+               $root['name'] = __('Labels');
+               $root['items'] = array();
+
+               $result = db_query($this->link, "SELECT *
+                       FROM ttrss_labels2
+                       WHERE owner_uid = ".$_SESSION["uid"]."
+                       ORDER BY caption");
+
+               while ($line = db_fetch_assoc($result)) {
+                       $label = array();
+                       $label['id'] = 'LABEL:' . $line['id'];
+                       $label['bare_id'] = $line['id'];
+                       $label['name'] = $line['caption'];
+                       $label['fg_color'] = $line['fg_color'];
+                       $label['bg_color'] = $line['bg_color'];
+                       $label['type'] = 'label';
+                       $label['checkbox'] = false;
+
+                       array_push($root['items'], $label);
+               }
+
+               $fl = array();
+               $fl['identifier'] = 'id';
+               $fl['label'] = 'name';
+               $fl['items'] = array($root);
+
+               print json_encode($fl);
+               return;
+       }
+
+       function colorset() {
+               $kind = db_escape_string($_REQUEST["kind"]);
+               $ids = split(',', db_escape_string($_REQUEST["ids"]));
+               $color = db_escape_string($_REQUEST["color"]);
+               $fg = db_escape_string($_REQUEST["fg"]);
+               $bg = db_escape_string($_REQUEST["bg"]);
+
+               foreach ($ids as $id) {
+
+                       if ($kind == "fg" || $kind == "bg") {
+                               db_query($this->link, "UPDATE ttrss_labels2 SET
+                                       ${kind}_color = '$color' WHERE id = '$id'
+                                       AND owner_uid = " . $_SESSION["uid"]);
+                       } else {
+                               db_query($this->link, "UPDATE ttrss_labels2 SET
+                                       fg_color = '$fg', bg_color = '$bg' WHERE id = '$id'
+                                       AND owner_uid = " . $_SESSION["uid"]);
+                       }
+
+                       $caption = db_escape_string(label_find_caption($this->link, $id, $_SESSION["uid"]));
+
+                       /* Remove cached data */
+
+                       db_query($this->link, "UPDATE ttrss_user_entries SET label_cache = ''
+                               WHERE label_cache LIKE '%$caption%' AND owner_uid = " . $_SESSION["uid"]);
+
+               }
+
+               return;
+       }
+
+       function colorreset() {
+               $ids = split(',', db_escape_string($_REQUEST["ids"]));
+
+               foreach ($ids as $id) {
+                       db_query($this->link, "UPDATE ttrss_labels2 SET
+                               fg_color = '', bg_color = '' WHERE id = '$id'
+                               AND owner_uid = " . $_SESSION["uid"]);
+
+                       $caption = db_escape_string(label_find_caption($this->link, $id, $_SESSION["uid"]));
+
+                       /* Remove cached data */
+
+                       db_query($this->link, "UPDATE ttrss_user_entries SET label_cache = ''
+                               WHERE label_cache LIKE '%$caption%' AND owner_uid = " . $_SESSION["uid"]);
+               }
+
+       }
+
+       function save() {
+
+               $id = db_escape_string($_REQUEST["id"]);
+               $caption = db_escape_string(trim($_REQUEST["caption"]));
+
+               db_query($this->link, "BEGIN");
+
+               $result = db_query($this->link, "SELECT caption FROM ttrss_labels2
+                       WHERE id = '$id' AND owner_uid = ". $_SESSION["uid"]);
+
+               if (db_num_rows($result) != 0) {
+                       $old_caption = db_fetch_result($result, 0, "caption");
+
+                       $result = db_query($this->link, "SELECT id FROM ttrss_labels2
+                               WHERE caption = '$caption' AND owner_uid = ". $_SESSION["uid"]);
+
+                       if (db_num_rows($result) == 0) {
+                               if ($caption) {
+                                       $result = db_query($this->link, "UPDATE ttrss_labels2 SET
+                                               caption = '$caption' WHERE id = '$id' AND
+                                               owner_uid = " . $_SESSION["uid"]);
+
+                                       /* Update filters that reference label being renamed */
+
+                                       $old_caption = db_escape_string($old_caption);
+
+                                       db_query($this->link, "UPDATE ttrss_filters SET
+                                               action_param = '$caption' WHERE action_param = '$old_caption'
+                                               AND action_id = 7
+                                               AND owner_uid = " . $_SESSION["uid"]);
+
+                                       print $_REQUEST["value"];
+                               } else {
+                                       print $old_caption;
+                               }
+                       } else {
+                               print $old_caption;
+                       }
+               }
+
+               db_query($this->link, "COMMIT");
+
+               return;
+       }
+
+       function remove() {
+
+               $ids = split(",", db_escape_string($_REQUEST["ids"]));
+
+               foreach ($ids as $id) {
+                       label_remove($this->link, $id, $_SESSION["uid"]);
+               }
+
+       }
+
+       function add() {
+               $caption = db_escape_string($_REQUEST["caption"]);
+               $output = db_escape_string($_REQUEST["output"]);
+
+               if ($caption) {
+
+                       if (label_create($this->link, $caption)) {
+                               if (!$output) {
+                                       print T_sprintf("Created label <b>%s</b>", htmlspecialchars($caption));
+                               }
+                       }
+
+                       if ($output == "select") {
+                               header("Content-Type: text/xml");
+
+                               print "<rpc-reply><payload>";
+
+                               print_label_select($this->link, "select_label",
+                                       $caption, "");
+
+                               print "</payload></rpc-reply>";
+                       }
+               }
+
+               return;
+       }
+
+       function index() {
+
+               $sort = db_escape_string($_REQUEST["sort"]);
+
+               if (!$sort || $sort == "undefined") {
+                       $sort = "caption";
+               }
+
+               $label_search = db_escape_string($_REQUEST["search"]);
+
+               if (array_key_exists("search", $_REQUEST)) {
+                       $_SESSION["prefs_label_search"] = $label_search;
+               } else {
+                       $label_search = $_SESSION["prefs_label_search"];
+               }
+
+               print "<div id=\"pref-label-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
+               print "<div id=\"pref-label-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
+               print "<div id=\"pref-label-toolbar\" dojoType=\"dijit.Toolbar\">";
+
+               print "<div dojoType=\"dijit.form.DropDownButton\">".
+                               "<span>" . __('Select')."</span>";
+               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
+               print "<div onclick=\"dijit.byId('labelTree').model.setAllChecked(true)\"
+                       dojoType=\"dijit.MenuItem\">".__('All')."</div>";
+               print "<div onclick=\"dijit.byId('labelTree').model.setAllChecked(false)\"
+                       dojoType=\"dijit.MenuItem\">".__('None')."</div>";
+               print "</div></div>";
+
+               print"<button dojoType=\"dijit.form.Button\" onclick=\"return addLabel()\">".
+                       __('Create label')."</button dojoType=\"dijit.form.Button\"> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedLabels()\">".
+                       __('Remove')."</button dojoType=\"dijit.form.Button\"> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"labelColorReset()\">".
+                       __('Clear colors')."</button dojoType=\"dijit.form.Button\">";
+
+
+               print "</div>"; #toolbar
+               print "</div>"; #pane
+               print "<div id=\"pref-label-content\" dojoType=\"dijit.layout.ContentPane\" region=\"center\">";
+
+               print "<div id=\"labellistLoading\">
+               <img src='images/indicator_tiny.gif'>".
+                __("Loading, please wait...")."</div>";
+
+               print "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"labelStore\"
+                       url=\"backend.php?op=pref-labels&method=getlabeltree\">
+               </div>
+               <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"labelModel\" store=\"labelStore\"
+               query=\"{id:'root'}\" rootId=\"root\"
+                       childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
+               </div>
+               <div dojoType=\"fox.PrefLabelTree\" id=\"labelTree\"
+                       model=\"labelModel\" openOnClick=\"true\">
+               <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
+                       Element.hide(\"labellistLoading\");
+               </script>
+               <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
+                       var id = String(item.id);
+                       var bare_id = id.substr(id.indexOf(':')+1);
+
+                       if (id.match('LABEL:')) {
+                               editLabel(bare_id);
+                       }
+               </script>
+               </div>";
+
+               print "</div>"; #pane
+               print "</div>"; #container
+
+       }
+}
+
+?>
diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php
new file mode 100644 (file)
index 0000000..ff8a17c
--- /dev/null
@@ -0,0 +1,499 @@
+<?php
+class Pref_Prefs extends Handler_Protected {
+
+       function csrf_ignore($method) {
+               $csrf_ignored = array("index");
+
+               return array_search($method, $csrf_ignored) !== false;
+       }
+
+       function changepassword() {
+
+               $old_pw = $_POST["old_password"];
+               $new_pw = $_POST["new_password"];
+               $con_pw = $_POST["confirm_password"];
+
+               if ($old_pw == "") {
+                       print "ERROR: ".__("Old password cannot be blank.");
+                       return;
+               }
+
+               if ($new_pw == "") {
+                       print "ERROR: ".__("New password cannot be blank.");
+                       return;
+               }
+
+               if ($new_pw != $con_pw) {
+                       print "ERROR: ".__("Entered passwords do not match.");
+                       return;
+               }
+
+               $module_class = "auth_" . $_SESSION["auth_module"];
+               $authenticator = new $module_class($this->link);
+
+               if (method_exists($authenticator, "change_password")) {
+                       print $authenticator->change_password($_SESSION["uid"], $old_pw, $new_pw);
+               } else {
+                       print "ERROR: ".__("Function not supported by authentication module.");
+               }
+       }
+
+       function saveconfig() {
+
+               $_SESSION["prefs_cache"] = false;
+
+               $orig_theme = get_pref($this->link, "_THEME_ID");
+
+               foreach (array_keys($_POST) as $pref_name) {
+
+                       $pref_name = db_escape_string($pref_name);
+                       $value = db_escape_string($_POST[$pref_name]);
+
+                       if ($pref_name == 'DIGEST_PREFERRED_TIME') {
+                               if (get_pref($this->link, 'DIGEST_PREFERRED_TIME') != $value) {
+
+                                       db_query($this->link, "UPDATE ttrss_users SET
+                                               last_digest_sent = NULL WHERE id = " . $_SESSION['uid']);
+
+                               }
+                       }
+
+                       set_pref($this->link, $pref_name, $value);
+
+               }
+
+               if ($orig_theme != get_pref($this->link, "_THEME_ID")) {
+                       print "PREFS_THEME_CHANGED";
+               } else {
+                       print __("The configuration was saved.");
+               }
+       }
+
+       function getHelp() {
+
+               $pref_name = db_escape_string($_REQUEST["pn"]);
+
+               $result = db_query($this->link, "SELECT help_text FROM ttrss_prefs
+                       WHERE pref_name = '$pref_name'");
+
+               if (db_num_rows($result) > 0) {
+                       $help_text = db_fetch_result($result, 0, "help_text");
+                       print $help_text;
+               } else {
+                       printf(__("Unknown option: %s"), $pref_name);
+               }
+       }
+
+       function changeemail() {
+
+               $email = db_escape_string($_POST["email"]);
+               $full_name = db_escape_string($_POST["full_name"]);
+
+               $active_uid = $_SESSION["uid"];
+
+               db_query($this->link, "UPDATE ttrss_users SET email = '$email',
+                       full_name = '$full_name' WHERE id = '$active_uid'");
+
+               print __("Your personal data has been saved.");
+
+               return;
+       }
+
+       function resetconfig() {
+
+               $_SESSION["prefs_op_result"] = "reset-to-defaults";
+
+               if ($_SESSION["profile"]) {
+                       $profile_qpart = "profile = '" . $_SESSION["profile"] . "'";
+               } else {
+                       $profile_qpart = "profile IS NULL";
+               }
+
+               db_query($this->link, "DELETE FROM ttrss_user_prefs
+                       WHERE $profile_qpart AND owner_uid = ".$_SESSION["uid"]);
+
+               initialize_user_prefs($this->link, $_SESSION["uid"], $_SESSION["profile"]);
+
+               print "PREFS_THEME_CHANGED";
+       }
+
+       function index() {
+
+               global $access_level_names;
+
+               $prefs_blacklist = array("HIDE_READ_FEEDS", "FEEDS_SORT_BY_UNREAD",
+                                       "STRIP_UNSAFE_TAGS");
+
+               $profile_blacklist = array("ALLOW_DUPLICATE_POSTS", "PURGE_OLD_DAYS",
+                                       "PURGE_UNREAD_ARTICLES", "DIGEST_ENABLE", "DIGEST_CATCHUP",
+                                       "BLACKLISTED_TAGS", "ENABLE_API_ACCESS", "UPDATE_POST_ON_CHECKSUM_CHANGE",
+                                       "DEFAULT_UPDATE_INTERVAL", "USER_TIMEZONE", "SORT_HEADLINES_BY_FEED_DATE",
+                                       "SSL_CERT_SERIAL", "DIGEST_PREFERRED_TIME");
+
+
+               $_SESSION["prefs_op_result"] = "";
+
+               print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
+               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Personal data / Authentication')."\">";
+
+               print "<form dojoType=\"dijit.form.Form\" id=\"changeUserdataForm\">";
+
+               print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
+               evt.preventDefault();
+               if (this.validate()) {
+                       notify_progress('Saving data...', true);
+
+                       new Ajax.Request('backend.php', {
+                               parameters: dojo.objectToQuery(this.getValues()),
+                               onComplete: function(transport) {
+                                       notify_callback2(transport);
+                       } });
+
+               }
+               </script>";
+
+               print "<table width=\"100%\" class=\"prefPrefsList\">";
+
+               $result = db_query($this->link, "SELECT email,full_name,
+                       access_level FROM ttrss_users
+                       WHERE id = ".$_SESSION["uid"]);
+
+               $email = htmlspecialchars(db_fetch_result($result, 0, "email"));
+               $full_name = htmlspecialchars(db_fetch_result($result, 0, "full_name"));
+
+               print "<tr><td width=\"40%\">".__('Full name')."</td>";
+               print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" name=\"full_name\" required=\"1\"
+                       value=\"$full_name\"></td></tr>";
+
+               print "<tr><td width=\"40%\">".__('E-mail')."</td>";
+               print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" name=\"email\" required=\"1\" value=\"$email\"></td></tr>";
+
+               if (!SINGLE_USER_MODE && !$_SESSION["hide_hello"]) {
+
+                       $access_level = db_fetch_result($result, 0, "access_level");
+                       print "<tr><td width=\"40%\">".__('Access level')."</td>";
+                       print "<td>" . $access_level_names[$access_level] . "</td></tr>";
+               }
+
+               print "</table>";
+
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-prefs\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"changeemail\">";
+
+               print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
+                       __("Save data")."</button>";
+
+               print "</form>";
+
+               if  ($_SESSION["auth_module"]) {
+                       $module_class = "auth_" . $_SESSION["auth_module"];
+                       $authenticator = new $module_class($this->link);
+               } else {
+                       $authenticator = false;
+               }
+
+               if ($authenticator && method_exists($authenticator, "change_password")) {
+
+                       $result = db_query($this->link, "SELECT id FROM ttrss_users
+                               WHERE id = ".$_SESSION["uid"]." AND pwd_hash
+                               = 'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'");
+
+                       if (db_num_rows($result) != 0) {
+                               print format_warning(__("Your password is at default value, please change it."), "default_pass_warning");
+                       }
+
+                       print "<form dojoType=\"dijit.form.Form\">";
+
+                       print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
+                       evt.preventDefault();
+                       if (this.validate()) {
+                               notify_progress('Changing password...', true);
+
+                               new Ajax.Request('backend.php', {
+                                       parameters: dojo.objectToQuery(this.getValues()),
+                                       onComplete: function(transport) {
+                                               notify('');
+                                               if (transport.responseText.indexOf('ERROR: ') == 0) {
+                                                       notify_error(transport.responseText.replace('ERROR: ', ''));
+                                               } else {
+                                                       notify_info(transport.responseText);
+                                                       var warn = $('default_pass_warning');
+                                                       if (warn) Element.hide(warn);
+                                               }
+                               }});
+                               this.reset();
+                       }
+                       </script>";
+
+                       print "<table width=\"100%\" class=\"prefPrefsList\">";
+
+                       print "<tr><td width=\"40%\">".__("Old password")."</td>";
+                       print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" type=\"password\" required=\"1\" name=\"old_password\"></td></tr>";
+
+                       print "<tr><td width=\"40%\">".__("New password")."</td>";
+
+                       print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" type=\"password\" required=\"1\"
+                               name=\"new_password\"></td></tr>";
+
+                       print "<tr><td width=\"40%\">".__("Confirm password")."</td>";
+
+                       print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" type=\"password\" required=\"1\" name=\"confirm_password\"></td></tr>";
+
+                       print "</table>";
+
+                       print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-prefs\">";
+                       print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"changepassword\">";
+
+                       print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
+                               __("Change password")."</button>";
+
+                       print "</form>";
+
+               }
+
+               print "</div>"; #pane
+
+               print "<div dojoType=\"dijit.layout.AccordionPane\" selected=\"true\" title=\"".__('Preferences')."\">";
+
+               print "<form dojoType=\"dijit.form.Form\" id=\"changeSettingsForm\">";
+
+               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) {
+                                       var msg = transport.responseText;
+                                       if (msg.match('PREFS_THEME_CHANGED')) {
+                                               window.location.reload();
+                                       } else {
+                                               notify_info(msg);
+                                       }
+                       } });
+               }
+               </script>";
+
+               print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
+
+               print '<div dojoType="dijit.layout.ContentPane" region="center" style="overflow-y : auto">';
+
+               if ($_SESSION["profile"]) {
+                       print_notice("Some preferences are only available in default profile.");
+               }
+
+               if ($_SESSION["profile"]) {
+                       initialize_user_prefs($this->link, $_SESSION["uid"], $_SESSION["profile"]);
+                       $profile_qpart = "profile = '" . $_SESSION["profile"] . "'";
+               } else {
+                       initialize_user_prefs($this->link, $_SESSION["uid"]);
+                       $profile_qpart = "profile IS NULL";
+               }
+
+               $result = db_query($this->link, "SELECT DISTINCT
+                       ttrss_user_prefs.pref_name,short_desc,help_text,value,type_name,
+                       section_name,def_value,section_id
+                       FROM ttrss_prefs,ttrss_prefs_types,ttrss_prefs_sections,ttrss_user_prefs
+                       WHERE type_id = ttrss_prefs_types.id AND
+                               $profile_qpart AND
+                               section_id = ttrss_prefs_sections.id AND
+                               ttrss_user_prefs.pref_name = ttrss_prefs.pref_name AND
+                               short_desc != '' AND
+                               owner_uid = ".$_SESSION["uid"]."
+                       ORDER BY section_id,short_desc");
+
+               $lnum = 0;
+
+               $active_section = "";
+
+               while ($line = db_fetch_assoc($result)) {
+
+                       if (in_array($line["pref_name"], $prefs_blacklist)) {
+                               continue;
+                       }
+
+                       if ($_SESSION["profile"] && in_array($line["pref_name"],
+                                       $profile_blacklist)) {
+                               continue;
+                       }
+
+                       if ($active_section != $line["section_name"]) {
+
+                               if ($active_section != "") {
+                                       print "</table>";
+                               }
+
+                               print "<table width=\"100%\" class=\"prefPrefsList\">";
+
+                               $active_section = $line["section_name"];
+
+                               print "<tr><td colspan=\"3\"><h3>".__($active_section)."</h3></td></tr>";
+
+                               if ($line["section_id"] == 2) {
+                                       print "<tr><td width=\"40%\">".__("Select theme")."</td>";
+
+                                       $user_theme = get_pref($this->link, "_THEME_ID");
+                                       $themes = get_all_themes();
+
+                                       print "<td><select name=\"_THEME_ID\" dojoType=\"dijit.form.Select\">";
+                                       print "<option value='Default'>".__('Default')."</option>";
+                                       print "<option value='----------------' disabled=\"1\">--------</option>";
+
+                                       foreach ($themes as $t) {
+                                               $base = $t['base'];
+                                               $name = $t['name'];
+
+                                               if ($base == $user_theme) {
+                                                       $selected = "selected=\"1\"";
+                                               } else {
+                                                       $selected = "";
+                                               }
+
+                                               print "<option $selected value='$base'>$name</option>";
+
+                                       }
+
+                                       print "</select></td></tr>";
+                               }
+                               $lnum = 0;
+                       }
+
+                       print "<tr>";
+
+                       $type_name = $line["type_name"];
+                       $pref_name = $line["pref_name"];
+                       $value = $line["value"];
+                       $def_value = $line["def_value"];
+                       $help_text = $line["help_text"];
+
+                       print "<td width=\"40%\" class=\"prefName\" id=\"$pref_name\">" . __($line["short_desc"]);
+
+                       if ($help_text) print "<div class=\"prefHelp\">".__($help_text)."</div>";
+
+                       print "</td>";
+
+                       print "<td class=\"prefValue\">";
+
+                       if ($pref_name == "USER_TIMEZONE") {
+
+                               $timezones = explode("\n", file_get_contents("lib/timezones.txt"));
+
+                               print_select($pref_name, $value, $timezones, 'dojoType="dijit.form.FilteringSelect"');
+                       } else if ($pref_name == "USER_STYLESHEET") {
+
+                               print "<button dojoType=\"dijit.form.Button\"
+                                       onclick=\"customizeCSS()\">" . __('Customize') . "</button>";
+
+                       } else if ($pref_name == "DEFAULT_ARTICLE_LIMIT") {
+
+                               $limits = array(15, 30, 45, 60);
+
+                               print_select($pref_name, $value, $limits,
+                                       'dojoType="dijit.form.Select"');
+
+                       } else if ($pref_name == "DEFAULT_UPDATE_INTERVAL") {
+
+                               global $update_intervals_nodefault;
+
+                               print_select_hash($pref_name, $value, $update_intervals_nodefault,
+                                       'dojoType="dijit.form.Select"');
+
+                       } else if ($type_name == "bool") {
+
+                               if ($value == "true") {
+                                       $value = __("Yes");
+                               } else {
+                                       $value = __("No");
+                               }
+
+                               if ($pref_name == "PURGE_UNREAD_ARTICLES" && FORCE_ARTICLE_PURGE != 0) {
+                                       $disabled = "disabled=\"1\"";
+                                       $value = __("Yes");
+                               } else {
+                                       $disabled = "";
+                               }
+
+                               print_radio($pref_name, $value, __("Yes"), array(__("Yes"), __("No")),
+                                       $disabled);
+
+                       } else if (array_search($pref_name, array('FRESH_ARTICLE_MAX_AGE', 'DEFAULT_ARTICLE_LIMIT',
+                                       'PURGE_OLD_DAYS', 'LONG_DATE_FORMAT', 'SHORT_DATE_FORMAT')) !== false) {
+
+                               $regexp = ($type_name == 'integer') ? 'regexp="^\d*$"' : '';
+
+                               if ($pref_name == "PURGE_OLD_DAYS" && FORCE_ARTICLE_PURGE != 0) {
+                                       $disabled = "disabled=\"1\"";
+                                       $value = FORCE_ARTICLE_PURGE;
+                               } else {
+                                       $disabled = "";
+                               }
+
+                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
+                                       required=\"1\" $regexp $disabled
+                                       name=\"$pref_name\" value=\"$value\">";
+
+                       } else if ($pref_name == "SSL_CERT_SERIAL") {
+
+                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
+                                       id=\"SSL_CERT_SERIAL\" readonly=\"1\"
+                                       name=\"$pref_name\" value=\"$value\">";
+
+                               $cert_serial = htmlspecialchars(get_ssl_certificate_id());
+                               $has_serial = ($cert_serial) ? "false" : "true";
+
+                               print " <button dojoType=\"dijit.form.Button\" disabled=\"$has_serial\"
+                                       onclick=\"insertSSLserial('$cert_serial')\">" .
+                                       __('Register') . "</button>";
+
+                               print " <button dojoType=\"dijit.form.Button\"
+                                       onclick=\"insertSSLserial('')\">" .
+                                       __('Clear') . "</button>";
+
+                       } else if ($pref_name == 'DIGEST_PREFERRED_TIME') {
+                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
+                                       id=\"$pref_name\" regexp=\"[012]?\d:\d\d\" placeHolder=\"12:00\"
+                                       name=\"$pref_name\" value=\"$value\"><div class=\"insensitive\">".
+                                       T_sprintf("Current server time: %s (UTC)", date("H:i")) . "</div>";
+                       } else {
+                               $regexp = ($type_name == 'integer') ? 'regexp="^\d*$"' : '';
+
+                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
+                                       $regexp
+                                       name=\"$pref_name\" value=\"$value\">";
+                       }
+
+                       print "</td>";
+
+                       print "</tr>";
+
+                       $lnum++;
+               }
+
+               print "</table>";
+
+               print '</div>'; # inside pane
+               print '<div dojoType="dijit.layout.ContentPane" region="bottom">';
+
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-prefs\">";
+               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"saveconfig\">";
+
+               print "<button dojoType=\"dijit.form.Button\" type=\"submit\">".
+                       __('Save configuration')."</button> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return editProfiles()\">".
+                       __('Manage profiles')."</button> ";
+
+               print "<button dojoType=\"dijit.form.Button\" onclick=\"return validatePrefsReset()\">".
+                       __('Reset to defaults')."</button>";
+
+               print '</div>'; # inner pane
+               print '</div>'; # border container
+
+               print "</form>";
+
+               print "</div>"; #pane
+               print "</div>"; #container
+       }
+}
+?>
diff --git a/classes/pref/users.php b/classes/pref/users.php
new file mode 100644 (file)
index 0000000..e54f899
--- /dev/null
@@ -0,0 +1,494 @@
+<?php
+class Pref_Users extends Handler_Protected {
+               function before($method) {
+                       if (parent::before($method)) {
+                               if ($_SESSION["access_level"] < 10) {
+                                       print __("Your access level is insufficient to open this tab.");
+                                       return false;
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
+               function csrf_ignore($method) {
+                       $csrf_ignored = array("index");
+
+                       return array_search($method, $csrf_ignored) !== false;
+               }
+
+               function userdetails() {
+
+                       header("Content-Type: text/xml");
+                       print "<dlg>";
+
+                       $uid = sprintf("%d", $_REQUEST["id"]);
+
+                       print "<title>".__('User details')."</title>";
+
+                       print "<content><![CDATA[";
+
+                       $result = db_query($this->link, "SELECT login,
+                               ".SUBSTRING_FOR_DATE."(last_login,1,16) AS last_login,
+                               access_level,
+                               (SELECT COUNT(int_id) FROM ttrss_user_entries
+                                       WHERE owner_uid = id) AS stored_articles,
+                               ".SUBSTRING_FOR_DATE."(created,1,16) AS created
+                               FROM ttrss_users
+                               WHERE id = '$uid'");
+
+                       if (db_num_rows($result) == 0) {
+                               print "<h1>".__('User not found')."</h1>";
+                               return;
+                       }
+
+                       // print "<h1>User Details</h1>";
+
+                       $login = db_fetch_result($result, 0, "login");
+
+                       print "<table width='100%'>";
+
+                       $last_login = make_local_datetime($this->link,
+                               db_fetch_result($result, 0, "last_login"), true);
+
+                       $created = make_local_datetime($this->link,
+                               db_fetch_result($result, 0, "created"), true);
+
+                       $access_level = db_fetch_result($result, 0, "access_level");
+                       $stored_articles = db_fetch_result($result, 0, "stored_articles");
+
+                       print "<tr><td>".__('Registered')."</td><td>$created</td></tr>";
+                       print "<tr><td>".__('Last logged in')."</td><td>$last_login</td></tr>";
+
+                       $result = db_query($this->link, "SELECT COUNT(id) as num_feeds FROM ttrss_feeds
+                               WHERE owner_uid = '$uid'");
+
+                       $num_feeds = db_fetch_result($result, 0, "num_feeds");
+
+                       print "<tr><td>".__('Subscribed feeds count')."</td><td>$num_feeds</td></tr>";
+
+                       print "</table>";
+
+                       print "<h1>".__('Subscribed feeds')."</h1>";
+
+                       $result = db_query($this->link, "SELECT id,title,site_url FROM ttrss_feeds
+                               WHERE owner_uid = '$uid' ORDER BY title");
+
+                       print "<ul class=\"userFeedList\">";
+
+                       $row_class = "odd";
+
+                       while ($line = db_fetch_assoc($result)) {
+
+                               $icon_file = ICONS_URL."/".$line["id"].".ico";
+
+                               if (file_exists($icon_file) && filesize($icon_file) > 0) {
+                                       $feed_icon = "<img class=\"tinyFeedIcon\" src=\"$icon_file\">";
+                               } else {
+                                       $feed_icon = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\">";
+                               }
+
+                               print "<li class=\"$row_class\">$feed_icon&nbsp;<a href=\"".$line["site_url"]."\">".$line["title"]."</a></li>";
+
+                               $row_class = $row_class == "even" ? "odd" : "even";
+
+                       }
+
+                       if (db_num_rows($result) < $num_feeds) {
+                               // FIXME - add link to show ALL subscribed feeds here somewhere
+                               print "<li><img
+                                       class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\">&nbsp;...</li>";
+                       }
+
+                       print "</ul>";
+
+                       print "<div align='center'>
+                               <button onclick=\"closeInfoBox()\">".__("Close this window").
+                               "</button></div>";
+
+                       print "]]></content></dlg>";
+
+                       return;
+               }
+
+               function edit() {
+                       global $access_level_names;
+
+                       header("Content-Type: text/xml");
+
+                       $id = db_escape_string($_REQUEST["id"]);
+
+                       print "<dlg id=\"$method\">";
+                       print "<title>".__('User Editor')."</title>";
+                       print "<content><![CDATA[";
+
+                       print "<form id=\"user_edit_form\" onsubmit='return false'>";
+
+                       print "<input type=\"hidden\" name=\"id\" value=\"$id\">";
+                       print "<input type=\"hidden\" name=\"op\" value=\"pref-users\">";
+                       print "<input type=\"hidden\" name=\"method\" value=\"editSave\">";
+
+                       $result = db_query($this->link, "SELECT * FROM ttrss_users WHERE id = '$id'");
+
+                       $login = db_fetch_result($result, 0, "login");
+                       $access_level = db_fetch_result($result, 0, "access_level");
+                       $email = db_fetch_result($result, 0, "email");
+
+                       $sel_disabled = ($id == $_SESSION["uid"]) ? "disabled" : "";
+
+                       print "<div class=\"dlgSec\">".__("User")."</div>";
+                       print "<div class=\"dlgSecCont\">";
+
+                       if ($sel_disabled) {
+                               print "<input type=\"hidden\" name=\"login\" value=\"$login\">";
+                               print "<input size=\"30\" style=\"font-size : 16px\"
+                                       onkeypress=\"return filterCR(event, userEditSave)\" $sel_disabled
+                                       value=\"$login\">";
+                       } else {
+                               print "<input size=\"30\" style=\"font-size : 16px\"
+                                       onkeypress=\"return filterCR(event, userEditSave)\" $sel_disabled
+                                       name=\"login\" value=\"$login\">";
+                       }
+
+                       print "</div>";
+
+                       print "<div class=\"dlgSec\">".__("Authentication")."</div>";
+                       print "<div class=\"dlgSecCont\">";
+
+                       print __('Access level: ') . " ";
+
+                       if (!$sel_disabled) {
+                               print_select_hash("access_level", $access_level, $access_level_names,
+                                       $sel_disabled);
+                       } else {
+                               print_select_hash("", $access_level, $access_level_names,
+                                       $sel_disabled);
+                               print "<input type=\"hidden\" name=\"access_level\" value=\"$access_level\">";
+                       }
+
+                       print "<br/>";
+
+                       print __('Change password to') .
+                               " <input size=\"20\" onkeypress=\"return filterCR(event, userEditSave)\"
+                               name=\"password\">";
+
+                       print "</div>";
+
+                       print "<div class=\"dlgSec\">".__("Options")."</div>";
+                       print "<div class=\"dlgSecCont\">";
+
+                       print __('E-mail: ').
+                               " <input size=\"30\" name=\"email\" onkeypress=\"return filterCR(event, userEditSave)\"
+                               value=\"$email\">";
+
+                       print "</div>";
+
+                       print "</table>";
+
+                       print "</form>";
+
+                       print "<div class=\"dlgButtons\">
+                               <button onclick=\"return userEditSave()\">".
+                                       __('Save')."</button>
+                               <button onclick=\"return userEditCancel()\">".
+                                       __('Cancel')."</button></div>";
+
+                       print "]]></content></dlg>";
+
+                       return;
+               }
+
+               function editSave() {
+                       $login = db_escape_string(trim($_REQUEST["login"]));
+                       $uid = db_escape_string($_REQUEST["id"]);
+                       $access_level = (int) $_REQUEST["access_level"];
+                       $email = db_escape_string(trim($_REQUEST["email"]));
+                       $password = db_escape_string(trim($_REQUEST["password"]));
+
+                       if ($password) {
+                               $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
+                               $pwd_hash = encrypt_password($password, $salt, true);
+                               $pass_query_part = "pwd_hash = '$pwd_hash', salt = '$salt',";
+                       } else {
+                               $pass_query_part = "";
+                       }
+
+                       db_query($this->link, "UPDATE ttrss_users SET $pass_query_part login = '$login',
+                               access_level = '$access_level', email = '$email' WHERE id = '$uid'");
+
+               }
+
+               function remove() {
+                       $ids = split(",", db_escape_string($_REQUEST["ids"]));
+
+                       foreach ($ids as $id) {
+                               if ($id != $_SESSION["uid"] && $id != 1) {
+                                       db_query($this->link, "DELETE FROM ttrss_tags WHERE owner_uid = '$id'");
+                                       db_query($this->link, "DELETE FROM ttrss_feeds WHERE owner_uid = '$id'");
+                                       db_query($this->link, "DELETE FROM ttrss_users WHERE id = '$id'");
+                               }
+                       }
+               }
+
+               function add() {
+
+                       $login = db_escape_string(trim($_REQUEST["login"]));
+                       $tmp_user_pwd = make_password(8);
+                       $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
+                       $pwd_hash = encrypt_password($tmp_user_pwd, $salt, true);
+
+                       $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
+                               login = '$login'");
+
+                       if (db_num_rows($result) == 0) {
+
+                               db_query($this->link, "INSERT INTO ttrss_users
+                                       (login,pwd_hash,access_level,last_login,created, salt)
+                                       VALUES ('$login', '$pwd_hash', 0, null, NOW(), '$salt')");
+
+
+                               $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
+                                       login = '$login' AND pwd_hash = '$pwd_hash'");
+
+                               if (db_num_rows($result) == 1) {
+
+                                       $new_uid = db_fetch_result($result, 0, "id");
+
+                                       print format_notice(T_sprintf("Added user <b>%s</b> with password <b>%s</b>",
+                                               $login, $tmp_user_pwd));
+
+                                       initialize_user($this->link, $new_uid);
+
+                               } else {
+
+                                       print format_warning(T_sprintf("Could not create user <b>%s</b>", $login));
+
+                               }
+                       } else {
+                               print format_warning(T_sprintf("User <b>%s</b> already exists.", $login));
+                       }
+               }
+
+               function resetPass() {
+
+                       $uid = db_escape_string($_REQUEST["id"]);
+
+                       $result = db_query($this->link, "SELECT login,email
+                               FROM ttrss_users WHERE id = '$uid'");
+
+                       $login = db_fetch_result($result, 0, "login");
+                       $email = db_fetch_result($result, 0, "email");
+                       $salt = db_fetch_result($result, 0, "salt");
+
+                       $new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
+                       $tmp_user_pwd = make_password(8);
+
+                       $pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true);
+
+                       db_query($this->link, "UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt'
+                               WHERE id = '$uid'");
+
+                       print T_sprintf("Changed password of user <b>%s</b>
+                                to <b>%s</b>", $login, $tmp_user_pwd);
+
+                       require_once 'lib/phpmailer/class.phpmailer.php';
+
+                       if ($email) {
+                               print " ";
+                               print T_sprintf("Notifying <b>%s</b>.", $email);
+
+                               require_once "lib/MiniTemplator.class.php";
+
+                               $tpl = new MiniTemplator;
+
+                               $tpl->readTemplateFromFile("templates/resetpass_template.txt");
+
+                               $tpl->setVariable('LOGIN', $login);
+                               $tpl->setVariable('NEWPASS', $tmp_user_pwd);
+
+                               $tpl->addBlock('message');
+
+                               $message = "";
+
+                               $tpl->generateOutputToString($message);
+
+                               $mail = new PHPMailer();
+
+                               $mail->PluginDir = "lib/phpmailer/";
+                               $mail->SetLanguage("en", "lib/phpmailer/language/");
+
+                               $mail->CharSet = "UTF-8";
+
+                               $mail->From = SMTP_FROM_ADDRESS;
+                               $mail->FromName = SMTP_FROM_NAME;
+                               $mail->AddAddress($email, $login);
+
+                               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 = __("[tt-rss] Password change notification");
+                               $mail->Body = $message;
+
+                               $rc = $mail->Send();
+
+                               if (!$rc) print_error($mail->ErrorInfo);
+                       }
+
+                       print "</div>";
+               }
+
+               function index() {
+
+                       global $access_level_names;
+
+                       print "<div id=\"pref-user-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
+                       print "<div id=\"pref-user-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
+
+                       print "<div id=\"pref-user-toolbar\" dojoType=\"dijit.Toolbar\">";
+
+                       $user_search = db_escape_string($_REQUEST["search"]);
+
+                       if (array_key_exists("search", $_REQUEST)) {
+                               $_SESSION["prefs_user_search"] = $user_search;
+                       } else {
+                               $user_search = $_SESSION["prefs_user_search"];
+                       }
+
+                       print "<div style='float : right; padding-right : 4px;'>
+                               <input dojoType=\"dijit.form.TextBox\" id=\"user_search\" size=\"20\" type=\"search\"
+                                       value=\"$user_search\">
+                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:updateUsersList()\">".
+                                       __('Search')."</button>
+                               </div>";
+
+                       $sort = db_escape_string($_REQUEST["sort"]);
+
+                       if (!$sort || $sort == "undefined") {
+                               $sort = "login";
+                       }
+
+                       print "<div dojoType=\"dijit.form.DropDownButton\">".
+                                       "<span>" . __('Select')."</span>";
+                       print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
+                       print "<div onclick=\"selectTableRows('prefUserList', 'all')\"
+                               dojoType=\"dijit.MenuItem\">".__('All')."</div>";
+                       print "<div onclick=\"selectTableRows('prefUserList', 'none')\"
+                               dojoType=\"dijit.MenuItem\">".__('None')."</div>";
+                       print "</div></div>";
+
+                       print "<button dojoType=\"dijit.form.Button\" onclick=\"javascript:addUser()\">".__('Create user')."</button>";
+
+                       print "
+                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:selectedUserDetails()\">".
+                               __('Details')."</button dojoType=\"dijit.form.Button\">
+                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:editSelectedUser()\">".
+                               __('Edit')."</button dojoType=\"dijit.form.Button\">
+                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:removeSelectedUsers()\">".
+                               __('Remove')."</button dojoType=\"dijit.form.Button\">
+                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:resetSelectedUserPass()\">".
+                               __('Reset password')."</button dojoType=\"dijit.form.Button\">";
+
+                       print "</div>"; #toolbar
+                       print "</div>"; #pane
+                       print "<div id=\"pref-user-content\" dojoType=\"dijit.layout.ContentPane\" region=\"center\">";
+
+                       print "<div id=\"sticky-status-msg\"></div>";
+
+                       if ($user_search) {
+
+                               $user_search = split(" ", $user_search);
+                               $tokens = array();
+
+                               foreach ($user_search as $token) {
+                                       $token = trim($token);
+                                       array_push($tokens, "(UPPER(login) LIKE UPPER('%$token%'))");
+                               }
+
+                               $user_search_query = "(" . join($tokens, " AND ") . ") AND ";
+
+                       } else {
+                               $user_search_query = "";
+                       }
+
+                       $result = db_query($this->link, "SELECT
+                                       id,login,access_level,email,
+                                       ".SUBSTRING_FOR_DATE."(last_login,1,16) as last_login,
+                                       ".SUBSTRING_FOR_DATE."(created,1,16) as created
+                               FROM
+                                       ttrss_users
+                               WHERE
+                                       $user_search_query
+                                       id > 0
+                               ORDER BY $sort");
+
+                       if (db_num_rows($result) > 0) {
+
+                       print "<p><table width=\"100%\" cellspacing=\"0\"
+                               class=\"prefUserList\" id=\"prefUserList\">";
+
+                       print "<tr class=\"title\">
+                                               <td align='center' width=\"5%\">&nbsp;</td>
+                                               <td width=''><a href=\"#\" onclick=\"updateUsersList('login')\">".__('Login')."</a></td>
+                                               <td width='20%'><a href=\"#\" onclick=\"updateUsersList('access_level')\">".__('Access Level')."</a></td>
+                                               <td width='20%'><a href=\"#\" onclick=\"updateUsersList('created')\">".__('Registered')."</a></td>
+                                               <td width='20%'><a href=\"#\" onclick=\"updateUsersList('last_login')\">".__('Last login')."</a></td></tr>";
+
+                       $lnum = 0;
+
+                       while ($line = db_fetch_assoc($result)) {
+
+                               $class = ($lnum % 2) ? "even" : "odd";
+
+                               $uid = $line["id"];
+
+                               print "<tr class=\"$class\" id=\"UMRR-$uid\">";
+
+                               $line["login"] = htmlspecialchars($line["login"]);
+
+                               $line["created"] = make_local_datetime($this->link, $line["created"], false);
+                               $line["last_login"] = make_local_datetime($this->link, $line["last_login"], false);
+
+                               print "<td align='center'><input onclick='toggleSelectRow(this);'
+                                       type=\"checkbox\" id=\"UMCHK-$uid\"></td>";
+
+                               $onclick = "onclick='editUser($uid, event)' title='".__('Click to edit')."'";
+
+                               print "<td $onclick>" . $line["login"] . "</td>";
+
+                               if (!$line["email"]) $line["email"] = "&nbsp;";
+
+                               print "<td $onclick>" . $access_level_names[$line["access_level"]] . "</td>";
+                               print "<td $onclick>" . $line["created"] . "</td>";
+                               print "<td $onclick>" . $line["last_login"] . "</td>";
+
+                               print "</tr>";
+
+                               ++$lnum;
+                       }
+
+                       print "</table>";
+
+                       } else {
+                               print "<p>";
+                               if (!$user_search) {
+                                       print_warning(__('No users defined.'));
+                               } else {
+                                       print_warning(__('No matching users found.'));
+                               }
+                               print "</p>";
+
+                       }
+
+                       print "</div>"; #pane
+                       print "</div>"; #container
+
+               }
+
+       }
+?>
diff --git a/classes/pref_feeds.php b/classes/pref_feeds.php
deleted file mode 100644 (file)
index b105611..0000000
+++ /dev/null
@@ -1,1681 +0,0 @@
-<?php
-class Pref_Feeds extends Protected_Handler {
-
-       function csrf_ignore($method) {
-               $csrf_ignored = array("index", "getfeedtree", "add", "editcats", "editfeed",
-                       "savefeedorder", "uploadicon");
-
-               return array_search($method, $csrf_ignored) !== false;
-       }
-
-       function batch_edit_cbox($elem, $label = false) {
-               print "<input type=\"checkbox\" title=\"".__("Check to enable field")."\"
-                       onchange=\"dijit.byId('feedEditDlg').toggleField(this, '$elem', '$label')\">";
-       }
-
-       function renamecat() {
-               $title = db_escape_string($_REQUEST['title']);
-               $id = db_escape_string($_REQUEST['id']);
-
-               if ($title) {
-                       db_query($this->link, "UPDATE ttrss_feed_categories SET
-                               title = '$title' WHERE id = '$id' AND owner_uid = " . $_SESSION["uid"]);
-               }
-               return;
-       }
-
-       function remtwitterinfo() {
-
-               db_query($this->link, "UPDATE ttrss_users SET twitter_oauth = NULL
-                       WHERE id = " . $_SESSION['uid']);
-
-               return;
-       }
-
-       private function get_category_items($cat_id) {
-               $show_empty_cats = $_REQUEST['mode'] != 2 &&
-                       get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
-
-               $items = array();
-
-               $result = db_query($this->link, "SELECT id, title, collapsed FROM ttrss_feed_categories
-                               WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat = '$cat_id' ORDER BY order_id, title");
-
-               while ($line = db_fetch_assoc($result)) {
-
-                       $cat = array();
-                       $cat['id'] = 'CAT:' . $line['id'];
-                       $cat['bare_id'] = (int)$line['id'];
-                       $cat['name'] = $line['title'];
-                       $cat['items'] = array();
-                       $cat['checkbox'] = false;
-                       $cat['hidden'] = sql_bool_to_bool($line['collapsed']);
-                       $cat['type'] = 'category';
-                       $cat['unread'] = 0;
-                       $cat['child_unread'] = 0;
-
-                       $cat['items'] = $this->get_category_items($line['id']);
-
-                       $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
-
-                       if (count($cat['items']) > 0 || $show_empty_cats)
-                               array_push($items, $cat);
-
-               }
-
-               $feed_result = db_query($this->link, "SELECT id, title, last_error,
-                       ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
-                       FROM ttrss_feeds
-                       WHERE cat_id = '$cat_id' AND owner_uid = ".$_SESSION["uid"].
-                       "$search_qpart ORDER BY order_id, title");
-
-               while ($feed_line = db_fetch_assoc($feed_result)) {
-                       $feed = array();
-                       $feed['id'] = 'FEED:' . $feed_line['id'];
-                       $feed['bare_id'] = (int)$feed_line['id'];
-                       $feed['name'] = $feed_line['title'];
-                       $feed['checkbox'] = false;
-                       $feed['unread'] = 0;
-                       $feed['error'] = $feed_line['last_error'];
-                       $feed['icon'] = getFeedIcon($feed_line['id']);
-                       $feed['param'] = make_local_datetime($this->link,
-                               $feed_line['last_updated'], true);
-
-                       array_push($items, $feed);
-               }
-
-               return $items;
-       }
-
-       function getfeedtree() {
-
-               $search = $_SESSION["prefs_feed_search"];
-
-               if ($search) $search_qpart = " AND LOWER(title) LIKE LOWER('%$search%')";
-
-               $root = array();
-               $root['id'] = 'root';
-               $root['name'] = __('Feeds');
-               $root['items'] = array();
-               $root['type'] = 'category';
-
-               $enable_cats = get_pref($this->link, 'ENABLE_FEED_CATS');
-
-               if ($_REQUEST['mode'] == 2) {
-
-                       if ($enable_cats) {
-                               $cat_hidden = get_pref($this->link, "_COLLAPSED_SPECIAL");
-                               $cat = $this->feedlist_init_cat(-1, $cat_hidden);
-                       } else {
-                               $cat['items'] = array();
-                       }
-
-                       foreach (array(-4, -3, -1, -2, 0) as $i) {
-                               array_push($cat['items'], $this->feedlist_init_feed($i));
-                       }
-
-                       if ($enable_cats) {
-                               array_push($root['items'], $cat);
-                       } else {
-                               $root['items'] = array_merge($root['items'], $cat['items']);
-                       }
-
-                       $result = db_query($this->link, "SELECT * FROM
-                               ttrss_labels2 WHERE owner_uid = ".$_SESSION['uid']." ORDER by caption");
-
-                       if (db_num_rows($result) > 0) {
-
-                               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
-                                       $cat_hidden = get_pref($this->link, "_COLLAPSED_LABELS");
-                                       $cat = $this->feedlist_init_cat(-2, $cat_hidden);
-                               } else {
-                                       $cat['items'] = array();
-                               }
-
-                               while ($line = db_fetch_assoc($result)) {
-
-                                       $label_id = -$line['id'] - 11;
-                                       $count = getFeedUnread($this->link, $label_id);
-
-                                       $feed = $this->feedlist_init_feed($label_id, false, $count);
-
-                                       $feed['fg_color'] = $line['fg_color'];
-                                       $feed['bg_color'] = $line['bg_color'];
-
-                                       array_push($cat['items'], $feed);
-                               }
-
-                               if ($enable_cats) {
-                                       array_push($root['items'], $cat);
-                               } else {
-                                       $root['items'] = array_merge($root['items'], $cat['items']);
-                               }
-                       }
-               }
-
-               if ($enable_cats) {
-                       $show_empty_cats = $_REQUEST['mode'] != 2 &&
-                               get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
-
-                       $result = db_query($this->link, "SELECT id, title, collapsed FROM ttrss_feed_categories
-                               WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat IS NULL ORDER BY order_id, title");
-
-                       while ($line = db_fetch_assoc($result)) {
-                               $cat = array();
-                               $cat['id'] = 'CAT:' . $line['id'];
-                               $cat['bare_id'] = (int)$line['id'];
-                               $cat['name'] = $line['title'];
-                               $cat['items'] = array();
-                               $cat['checkbox'] = false;
-                               $cat['hidden'] = sql_bool_to_bool($line['collapsed']);
-                               $cat['type'] = 'category';
-                               $cat['unread'] = 0;
-                               $cat['child_unread'] = 0;
-
-                               $cat['items'] = $this->get_category_items($line['id']);
-
-                               $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
-
-                               if (count($cat['items']) > 0 || $show_empty_cats)
-                                       array_push($root['items'], $cat);
-
-                               $root['param'] += count($cat['items']);
-                       }
-
-                       /* Uncategorized is a special case */
-
-                       $cat = array();
-                       $cat['id'] = 'CAT:0';
-                       $cat['bare_id'] = 0;
-                       $cat['name'] = __("Uncategorized");
-                       $cat['items'] = array();
-                       $cat['hidden'] = get_pref($this->link, "_COLLAPSED_UNCAT");
-                       $cat['type'] = 'category';
-                       $cat['checkbox'] = false;
-                       $cat['unread'] = 0;
-                       $cat['child_unread'] = 0;
-
-                       $feed_result = db_query($this->link, "SELECT id, title,last_error,
-                               ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
-                               FROM ttrss_feeds
-                               WHERE cat_id IS NULL AND owner_uid = ".$_SESSION["uid"].
-                               "$search_qpart ORDER BY order_id, title");
-
-                       while ($feed_line = db_fetch_assoc($feed_result)) {
-                               $feed = array();
-                               $feed['id'] = 'FEED:' . $feed_line['id'];
-                               $feed['bare_id'] = (int)$feed_line['id'];
-                               $feed['name'] = $feed_line['title'];
-                               $feed['checkbox'] = false;
-                               $feed['error'] = $feed_line['last_error'];
-                               $feed['icon'] = getFeedIcon($feed_line['id']);
-                               $feed['param'] = make_local_datetime($this->link,
-                                       $feed_line['last_updated'], true);
-                               $feed['unread'] = 0;
-                               $feed['type'] = 'feed';
-
-                               array_push($cat['items'], $feed);
-                       }
-
-                       $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
-
-                       if (count($cat['items']) > 0 || $show_empty_cats)
-                               array_push($root['items'], $cat);
-
-                       $root['param'] += count($cat['items']);
-                       $root['param'] = T_sprintf('(%d feeds)', $root['param']);
-
-               } else {
-                       $feed_result = db_query($this->link, "SELECT id, title, last_error,
-                               ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
-                               FROM ttrss_feeds
-                               WHERE owner_uid = ".$_SESSION["uid"].
-                               "$search_qpart ORDER BY order_id, title");
-
-                       while ($feed_line = db_fetch_assoc($feed_result)) {
-                               $feed = array();
-                               $feed['id'] = 'FEED:' . $feed_line['id'];
-                               $feed['bare_id'] = (int)$feed_line['id'];
-                               $feed['name'] = $feed_line['title'];
-                               $feed['checkbox'] = false;
-                               $feed['error'] = $feed_line['last_error'];
-                               $feed['icon'] = getFeedIcon($feed_line['id']);
-                               $feed['param'] = make_local_datetime($this->link,
-                                       $feed_line['last_updated'], true);
-                               $feed['unread'] = 0;
-                               $feed['type'] = 'feed';
-
-                               array_push($root['items'], $feed);
-                       }
-
-                       $root['param'] = T_sprintf('(%d feeds)', count($root['items']));
-               }
-
-               $fl = array();
-               $fl['identifier'] = 'id';
-               $fl['label'] = 'name';
-
-               if ($_REQUEST['mode'] != 2) {
-                       $fl['items'] = array($root);
-               } else {
-                       $fl['items'] =& $root['items'];
-               }
-
-               print json_encode($fl);
-               return;
-       }
-
-       function catsortreset() {
-               db_query($this->link, "UPDATE ttrss_feed_categories
-                               SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
-               return;
-       }
-
-       function feedsortreset() {
-               db_query($this->link, "UPDATE ttrss_feeds
-                               SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
-               return;
-       }
-
-       function togglehiddenfeedcats() {
-               set_pref($this->link, '_PREFS_SHOW_EMPTY_CATS',
-                       (get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS') ? 'false' : 'true'));
-       }
-
-       private function process_category_order(&$data_map, $item_id, $parent_id = false, $nest_level = 0) {
-               $debug = isset($_REQUEST["debug"]);
-
-               $prefix = "";
-               for ($i = 0; $i < $nest_level; $i++)
-                       $prefix .= "   ";
-
-               if ($debug) _debug("$prefix C: $item_id P: $parent_id");
-
-               $bare_item_id = substr($item_id, strpos($item_id, ':')+1);
-
-               if ($item_id != 'root') {
-                       if ($parent_id && $parent_id != 'root') {
-                               $parent_bare_id = substr($parent_id, strpos($parent_id, ':')+1);
-                               $parent_qpart = db_escape_string($parent_bare_id);
-                       } else {
-                               $parent_qpart = 'NULL';
-                       }
-
-                       db_query($this->link, "UPDATE ttrss_feed_categories
-                               SET parent_cat = $parent_qpart WHERE id = '$bare_item_id' AND
-                               owner_uid = " . $_SESSION["uid"]);
-               }
-
-               $order_id = 0;
-
-               $cat = $data_map[$item_id];
-
-               if ($cat && is_array($cat)) {
-                       foreach ($cat as $item) {
-                               $id = $item['_reference'];
-                               $bare_id = substr($id, strpos($id, ':')+1);
-
-                               if ($debug) _debug("$prefix [$order_id] $id/$bare_id");
-
-                               if ($item['_reference']) {
-
-                                       if (strpos($id, "FEED") === 0) {
-
-                                               $cat_id = ($item_id != "root") ?
-                                                       db_escape_string($bare_item_id) : "NULL";
-
-                                               db_query($this->link, "UPDATE ttrss_feeds
-                                                       SET order_id = $order_id, cat_id = '$cat_id'
-                                                       WHERE id = '$bare_id' AND
-                                                               owner_uid = " . $_SESSION["uid"]);
-
-                                       } else if (strpos($id, "CAT:") === 0) {
-                                               $this->process_category_order($data_map, $item['_reference'], $item_id,
-                                                       $nest_level+1);
-
-                                               if ($item_id != 'root') {
-                                                       $parent_qpart = db_escape_string($bare_id);
-                                               } else {
-                                                       $parent_qpart = 'NULL';
-                                               }
-
-                                               db_query($this->link, "UPDATE ttrss_feed_categories
-                                                               SET order_id = '$order_id' WHERE id = '$bare_id' AND
-                                                               owner_uid = " . $_SESSION["uid"]);
-                                       }
-                               }
-
-                               ++$order_id;
-                       }
-               }
-       }
-
-       function savefeedorder() {
-               $data = json_decode($_POST['payload'], true);
-
-               #file_put_contents("/tmp/saveorder.json", $_POST['payload']);
-               #$data = json_decode(file_get_contents("/tmp/saveorder.json"), true);
-
-               if (!is_array($data['items']))
-                       $data['items'] = json_decode($data['items'], true);
-
-#              print_r($data['items']);
-
-               if (is_array($data) && is_array($data['items'])) {
-                       $cat_order_id = 0;
-
-                       $data_map = array();
-                       $root_item = false;
-
-                       foreach ($data['items'] as $item) {
-
-#                              if ($item['id'] != 'root') {
-                                       if (is_array($item['items'])) {
-                                               if (isset($item['items']['_reference'])) {
-                                                       $data_map[$item['id']] = array($item['items']);
-                                               } else {
-                                                       $data_map[$item['id']] =& $item['items'];
-                                               }
-                                       }
-                               if ($item['id'] == 'root') {
-                                       $root_item = $item['id'];
-                               }
-                       }
-
-                       $this->process_category_order($data_map, $root_item);
-
-                       /* foreach ($data['items'][0]['items'] as $item) {
-                               $id = $item['_reference'];
-                               $bare_id = substr($id, strpos($id, ':')+1);
-
-                               ++$cat_order_id;
-
-                               if ($bare_id > 0) {
-                                       db_query($this->link, "UPDATE ttrss_feed_categories
-                                               SET order_id = '$cat_order_id' WHERE id = '$bare_id' AND
-                                               owner_uid = " . $_SESSION["uid"]);
-                               }
-
-                               $feed_order_id = 0;
-
-                               if (is_array($data_map[$id])) {
-                                       foreach ($data_map[$id] as $feed) {
-                                               $id = $feed['_reference'];
-                                               $feed_id = substr($id, strpos($id, ':')+1);
-
-                                               if ($bare_id != 0)
-                                                       $cat_query = "cat_id = '$bare_id'";
-                                               else
-                                                       $cat_query = "cat_id = NULL";
-
-                                               db_query($this->link, "UPDATE ttrss_feeds
-                                                       SET order_id = '$feed_order_id',
-                                                       $cat_query
-                                                       WHERE id = '$feed_id' AND
-                                                               owner_uid = " . $_SESSION["uid"]);
-
-                                               ++$feed_order_id;
-                                       }
-                               }
-                       } */
-               }
-
-               return;
-       }
-
-       function removeicon() {
-               $feed_id = db_escape_string($_REQUEST["feed_id"]);
-
-               $result = db_query($this->link, "SELECT id FROM ttrss_feeds
-                       WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
-
-               if (db_num_rows($result) != 0) {
-                       unlink(ICONS_DIR . "/$feed_id.ico");
-               }
-
-               return;
-       }
-
-       function uploadicon() {
-               $icon_file = $_FILES['icon_file']['tmp_name'];
-               $feed_id = db_escape_string($_REQUEST["feed_id"]);
-
-               if (is_file($icon_file) && $feed_id) {
-                       if (filesize($icon_file) < 20000) {
-
-                               $result = db_query($this->link, "SELECT id FROM ttrss_feeds
-                                       WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
-
-                               if (db_num_rows($result) != 0) {
-                                       unlink(ICONS_DIR . "/$feed_id.ico");
-                                       move_uploaded_file($icon_file, ICONS_DIR . "/$feed_id.ico");
-                                       $rc = 0;
-                               } else {
-                                       $rc = 2;
-                               }
-                       } else {
-                               $rc = 1;
-                       }
-               } else {
-                       $rc = 2;
-               }
-
-               print "<script type=\"text/javascript\">";
-               print "parent.uploadIconHandler($rc);";
-               print "</script>";
-               return;
-       }
-
-       function editfeed() {
-               global $purge_intervals;
-               global $update_intervals;
-               global $update_methods;
-
-               $feed_id = db_escape_string($_REQUEST["id"]);
-
-               $result = db_query($this->link,
-                       "SELECT * FROM ttrss_feeds WHERE id = '$feed_id' AND
-                               owner_uid = " . $_SESSION["uid"]);
-
-               $title = htmlspecialchars(db_fetch_result($result,
-                       0, "title"));
-
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$feed_id\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"editSave\">";
-
-               print "<div class=\"dlgSec\">".__("Feed")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               /* Title */
-
-               print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
-                       placeHolder=\"".__("Feed Title")."\"
-                       style=\"font-size : 16px; width: 20em\" name=\"title\" value=\"$title\">";
-
-               /* Feed URL */
-
-               $feed_url = db_fetch_result($result, 0, "feed_url");
-               $feed_url = htmlspecialchars(db_fetch_result($result,
-                       0, "feed_url"));
-
-               print "<hr/>";
-
-               print __('URL:') . " ";
-               print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
-                       placeHolder=\"".__("Feed URL")."\"
-                       regExp='^(http|https)://.*' style=\"width : 20em\"
-                       name=\"feed_url\" value=\"$feed_url\">";
-
-               $last_error = db_fetch_result($result, 0, "last_error");
-
-               if ($last_error) {
-                       print "&nbsp;<span title=\"".htmlspecialchars($last_error)."\"
-                               class=\"feed_error\">(error)</span>";
-
-               }
-
-               /* Category */
-
-               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
-
-                       $cat_id = db_fetch_result($result, 0, "cat_id");
-
-                       print "<hr/>";
-
-                       print __('Place in category:') . " ";
-
-                       print_feed_cat_select($this->link, "cat_id", $cat_id,
-                               'dojoType="dijit.form.Select"');
-               }
-
-               print "</div>";
-
-               print "<div class=\"dlgSec\">".__("Update")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               /* Update Interval */
-
-               $update_interval = db_fetch_result($result, 0, "update_interval");
-
-               print_select_hash("update_interval", $update_interval, $update_intervals,
-                       'dojoType="dijit.form.Select"');
-
-               /* Update method */
-
-               $update_method = db_fetch_result($result, 0, "update_method",
-                       'dojoType="dijit.form.Select"');
-
-               print " " . __('using') . " ";
-               print_select_hash("update_method", $update_method, $update_methods,
-                       'dojoType="dijit.form.Select"');
-
-               $purge_interval = db_fetch_result($result, 0, "purge_interval");
-
-
-                       /* Purge intl */
-
-               print "<hr/>";
-               print __('Article purging:') . " ";
-
-               print_select_hash("purge_interval", $purge_interval, $purge_intervals,
-                       'dojoType="dijit.form.Select" ' .
-                               ((FORCE_ARTICLE_PURGE == 0) ? "" : 'disabled="1"'));
-
-               print "</div>";
-               print "<div class=\"dlgSec\">".__("Authentication")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               $auth_login = htmlspecialchars(db_fetch_result($result, 0, "auth_login"));
-
-               print "<input dojoType=\"dijit.form.TextBox\" id=\"feedEditDlg_login\"
-                       placeHolder=\"".__("Login")."\"
-                       name=\"auth_login\" value=\"$auth_login\"><hr/>";
-
-               $auth_pass = htmlspecialchars(db_fetch_result($result, 0, "auth_pass"));
-
-               print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
-                       placeHolder=\"".__("Password")."\"
-                       value=\"$auth_pass\">";
-
-               print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedEditDlg_login\" position=\"below\">
-                       ".__('<b>Hint:</b> you need to fill in your login information if your feed requires authentication, except for Twitter feeds.')."
-                       </div>";
-
-               print "</div>";
-               print "<div class=\"dlgSec\">".__("Options")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               $private = sql_bool_to_bool(db_fetch_result($result, 0, "private"));
-
-               if ($private) {
-                       $checked = "checked=\"1\"";
-               } else {
-                       $checked = "";
-               }
-
-               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"private\" id=\"private\"
-                       $checked>&nbsp;<label for=\"private\">".__('Hide from Popular feeds')."</label>";
-
-               $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
-
-               if ($rtl_content) {
-                       $checked = "checked=\"1\"";
-               } else {
-                       $checked = "";
-               }
-
-               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
-                       $checked>&nbsp;<label for=\"rtl_content\">".__('Right-to-left content')."</label>";
-
-               $include_in_digest = sql_bool_to_bool(db_fetch_result($result, 0, "include_in_digest"));
-
-               if ($include_in_digest) {
-                       $checked = "checked=\"1\"";
-               } else {
-                       $checked = "";
-               }
-
-               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"include_in_digest\"
-                       name=\"include_in_digest\"
-                       $checked>&nbsp;<label for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
-
-
-               $always_display_enclosures = sql_bool_to_bool(db_fetch_result($result, 0, "always_display_enclosures"));
-
-               if ($always_display_enclosures) {
-                       $checked = "checked";
-               } else {
-                       $checked = "";
-               }
-
-               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"always_display_enclosures\"
-                       name=\"always_display_enclosures\"
-                       $checked>&nbsp;<label for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
-
-
-               $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
-
-               if ($cache_images) {
-                       $checked = "checked=\"1\"";
-               } else {
-                       $checked = "";
-               }
-
-               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"cache_images\"
-               name=\"cache_images\"
-                       $checked>&nbsp;<label for=\"cache_images\">".
-               __('Cache images locally')."</label>";
-
-               $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
-
-               if ($mark_unread_on_update) {
-                       $checked = "checked";
-               } else {
-                       $checked = "";
-               }
-
-               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"mark_unread_on_update\"
-                       name=\"mark_unread_on_update\"
-                       $checked>&nbsp;<label for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
-
-               $update_on_checksum_change = sql_bool_to_bool(db_fetch_result($result, 0, "update_on_checksum_change"));
-
-               if ($update_on_checksum_change) {
-                       $checked = "checked";
-               } else {
-                       $checked = "";
-               }
-
-               print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"update_on_checksum_change\"
-                       name=\"update_on_checksum_change\"
-                       $checked>&nbsp;<label for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
-
-               print "</div>";
-
-               /* Icon */
-
-               print "<div class=\"dlgSec\">".__("Icon")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               print "<iframe name=\"icon_upload_iframe\"
-                       style=\"width: 400px; height: 100px; display: none;\"></iframe>";
-
-               print "<form style='display : block' target=\"icon_upload_iframe\"
-                       enctype=\"multipart/form-data\" method=\"POST\"
-                       action=\"backend.php\">
-                       <input id=\"icon_file\" size=\"10\" name=\"icon_file\" type=\"file\">
-                       <input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
-                       <input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
-                       <input type=\"hidden\" name=\"method\" value=\"uploadicon\">
-                       <button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
-                               type=\"submit\">".__('Replace')."</button>
-                       <button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
-                               type=\"submit\">".__('Remove')."</button>
-                       </form>";
-
-               print "</div>";
-
-               $title = htmlspecialchars($title, ENT_QUOTES);
-
-               print "<div class='dlgButtons'>
-                       <div style=\"float : left\">
-                       <button dojoType=\"dijit.form.Button\" onclick='return unsubscribeFeed($feed_id, \"$title\")'>".
-                               __('Unsubscribe')."</button>";
-
-               if (PUBSUBHUBBUB_ENABLED) {
-                       $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
-                       $pubsub_btn_disabled = ($pubsub_state == 2) ? "" : "disabled=\"1\"";
-
-                       print "<button dojoType=\"dijit.form.Button\" id=\"pubsubReset_Btn\" $pubsub_btn_disabled
-                                       onclick='return resetPubSub($feed_id, \"$title\")'>".__('Resubscribe to push updates').
-                                       "</button>";
-               }
-
-               print "</div>";
-
-               print "<div dojoType=\"dijit.Tooltip\" connectId=\"pubsubReset_Btn\" position=\"below\">".
-                       __('Resets PubSubHubbub subscription status for push-enabled feeds.')."</div>";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').execute()\">".__('Save')."</button>
-                       <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').hide()\">".__('Cancel')."</button>
-               </div>";
-
-               return;
-       }
-
-       function editfeeds() {
-               global $purge_intervals;
-               global $update_intervals;
-               global $update_methods;
-
-               $feed_ids = db_escape_string($_REQUEST["ids"]);
-
-               print "<div class=\"dialogNotice\">" . __("Enable the options you wish to apply using checkboxes on the right:") . "</div>";
-
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"ids\" value=\"$feed_ids\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"batchEditSave\">";
-
-               print "<div class=\"dlgSec\">".__("Feed")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               /* Title */
-
-               print "<input dojoType=\"dijit.form.ValidationTextBox\"
-                       disabled=\"1\" style=\"font-size : 16px; width : 20em;\" required=\"1\"
-                       name=\"title\" value=\"$title\">";
-
-               $this->batch_edit_cbox("title");
-
-               /* Feed URL */
-
-               print "<br/>";
-
-               print __('URL:') . " ";
-               print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\"
-                       required=\"1\" regExp='^(http|https)://.*' style=\"width : 20em\"
-                       name=\"feed_url\" value=\"$feed_url\">";
-
-               $this->batch_edit_cbox("feed_url");
-
-               /* Category */
-
-               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
-
-                       print "<br/>";
-
-                       print __('Place in category:') . " ";
-
-                       print_feed_cat_select($this->link, "cat_id", $cat_id,
-                               'disabled="1" dojoType="dijit.form.Select"');
-
-                       $this->batch_edit_cbox("cat_id");
-
-               }
-
-               print "</div>";
-
-               print "<div class=\"dlgSec\">".__("Update")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               /* Update Interval */
-
-               print_select_hash("update_interval", $update_interval, $update_intervals,
-                       'disabled="1" dojoType="dijit.form.Select"');
-
-               $this->batch_edit_cbox("update_interval");
-
-               /* Update method */
-
-               print " " . __('using') . " ";
-               print_select_hash("update_method", $update_method, $update_methods,
-                       'disabled="1" dojoType="dijit.form.Select"');
-               $this->batch_edit_cbox("update_method");
-
-               /* Purge intl */
-
-               if (FORCE_ARTICLE_PURGE == 0) {
-
-                       print "<br/>";
-
-                       print __('Article purging:') . " ";
-
-                       print_select_hash("purge_interval", $purge_interval, $purge_intervals,
-                               'disabled="1" dojoType="dijit.form.Select"');
-
-                       $this->batch_edit_cbox("purge_interval");
-               }
-
-               print "</div>";
-               print "<div class=\"dlgSec\">".__("Authentication")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               print "<input dojoType=\"dijit.form.TextBox\"
-                       placeHolder=\"".__("Login")."\" disabled=\"1\"
-                       name=\"auth_login\" value=\"$auth_login\">";
-
-               $this->batch_edit_cbox("auth_login");
-
-               print "<br/><input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
-                       placeHolder=\"".__("Password")."\" disabled=\"1\"
-                       value=\"$auth_pass\">";
-
-               $this->batch_edit_cbox("auth_pass");
-
-               print "</div>";
-               print "<div class=\"dlgSec\">".__("Options")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               print "<input disabled=\"1\" type=\"checkbox\" name=\"private\" id=\"private\"
-                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"private_l\" class='insensitive' for=\"private\">".__('Hide from Popular feeds')."</label>";
-
-               print "&nbsp;"; $this->batch_edit_cbox("private", "private_l");
-
-               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
-                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"rtl_content_l\" for=\"rtl_content\">".__('Right-to-left content')."</label>";
-
-               print "&nbsp;"; $this->batch_edit_cbox("rtl_content", "rtl_content_l");
-
-               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"include_in_digest\"
-                       name=\"include_in_digest\"
-                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"include_in_digest_l\" class='insensitive' for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
-
-               print "&nbsp;"; $this->batch_edit_cbox("include_in_digest", "include_in_digest_l");
-
-               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"always_display_enclosures\"
-                       name=\"always_display_enclosures\"
-                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"always_display_enclosures_l\" class='insensitive' for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
-
-               print "&nbsp;"; $this->batch_edit_cbox("always_display_enclosures", "always_display_enclosures_l");
-
-               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"cache_images\"
-                       name=\"cache_images\"
-                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"cache_images_l\"
-                       for=\"cache_images\">".
-               __('Cache images locally')."</label>";
-
-               print "&nbsp;"; $this->batch_edit_cbox("cache_images", "cache_images_l");
-
-               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"mark_unread_on_update\"
-                       name=\"mark_unread_on_update\"
-                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"mark_unread_on_update_l\" class='insensitive' for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
-
-               print "&nbsp;"; $this->batch_edit_cbox("mark_unread_on_update", "mark_unread_on_update_l");
-
-               print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"update_on_checksum_change\"
-                       name=\"update_on_checksum_change\"
-                       dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"update_on_checksum_change_l\" class='insensitive' for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
-
-               print "&nbsp;"; $this->batch_edit_cbox("update_on_checksum_change", "update_on_checksum_change_l");
-
-               print "</div>";
-
-               print "<div class='dlgButtons'>
-                       <button dojoType=\"dijit.form.Button\"
-                               onclick=\"return dijit.byId('feedEditDlg').execute()\">".
-                               __('Save')."</button>
-                       <button dojoType=\"dijit.form.Button\"
-                       onclick=\"return dijit.byId('feedEditDlg').hide()\">".
-                               __('Cancel')."</button>
-                       </div>";
-
-               return;
-       }
-
-       function batchEditSave() {
-               return $this->editsaveops(true);
-       }
-
-       function editSave() {
-               return $this->editsaveops(false);
-       }
-
-       function editsaveops($batch) {
-
-               $feed_title = db_escape_string(trim($_POST["title"]));
-               $feed_link = db_escape_string(trim($_POST["feed_url"]));
-               $upd_intl = (int) db_escape_string($_POST["update_interval"]);
-               $purge_intl = (int) db_escape_string($_POST["purge_interval"]);
-               $feed_id = (int) db_escape_string($_POST["id"]); /* editSave */
-               $feed_ids = db_escape_string($_POST["ids"]); /* batchEditSave */
-               $cat_id = (int) db_escape_string($_POST["cat_id"]);
-               $auth_login = db_escape_string(trim($_POST["auth_login"]));
-               $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
-               $private = checkbox_to_sql_bool(db_escape_string($_POST["private"]));
-               $rtl_content = checkbox_to_sql_bool(db_escape_string($_POST["rtl_content"]));
-               $include_in_digest = checkbox_to_sql_bool(
-                       db_escape_string($_POST["include_in_digest"]));
-               $cache_images = checkbox_to_sql_bool(
-                       db_escape_string($_POST["cache_images"]));
-               $update_method = (int) db_escape_string($_POST["update_method"]);
-
-               $always_display_enclosures = checkbox_to_sql_bool(
-                       db_escape_string($_POST["always_display_enclosures"]));
-
-               $mark_unread_on_update = checkbox_to_sql_bool(
-                       db_escape_string($_POST["mark_unread_on_update"]));
-
-               $update_on_checksum_change = checkbox_to_sql_bool(
-                       db_escape_string($_POST["update_on_checksum_change"]));
-
-               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
-                       if ($cat_id && $cat_id != 0) {
-                               $category_qpart = "cat_id = '$cat_id',";
-                               $category_qpart_nocomma = "cat_id = '$cat_id'";
-                       } else {
-                               $category_qpart = 'cat_id = NULL,';
-                               $category_qpart_nocomma = 'cat_id = NULL';
-                       }
-               } else {
-                       $category_qpart = "";
-                       $category_qpart_nocomma = "";
-               }
-
-               $cache_images_qpart = "cache_images = $cache_images,";
-
-               if (!$batch) {
-
-                       $result = db_query($this->link, "UPDATE ttrss_feeds SET
-                               $category_qpart
-                               title = '$feed_title', feed_url = '$feed_link',
-                               update_interval = '$upd_intl',
-                               purge_interval = '$purge_intl',
-                               auth_login = '$auth_login',
-                               auth_pass = '$auth_pass',
-                               private = $private,
-                               rtl_content = $rtl_content,
-                               $cache_images_qpart
-                               include_in_digest = $include_in_digest,
-                               always_display_enclosures = $always_display_enclosures,
-                               mark_unread_on_update = $mark_unread_on_update,
-                               update_on_checksum_change = $update_on_checksum_change,
-                               update_method = '$update_method'
-                               WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
-
-               } else {
-                       $feed_data = array();
-
-                       foreach (array_keys($_POST) as $k) {
-                               if ($k != "op" && $k != "method" && $k != "ids") {
-                                       $feed_data[$k] = $_POST[$k];
-                               }
-                       }
-
-                       db_query($this->link, "BEGIN");
-
-                       foreach (array_keys($feed_data) as $k) {
-
-                               $qpart = "";
-
-                               switch ($k) {
-                                       case "title":
-                                               $qpart = "title = '$feed_title'";
-                                               break;
-
-                                       case "feed_url":
-                                               $qpart = "feed_url = '$feed_link'";
-                                               break;
-
-                                       case "update_interval":
-                                               $qpart = "update_interval = '$upd_intl'";
-                                               break;
-
-                                       case "purge_interval":
-                                               $qpart = "purge_interval = '$purge_intl'";
-                                               break;
-
-                                       case "auth_login":
-                                               $qpart = "auth_login = '$auth_login'";
-                                               break;
-
-                                       case "auth_pass":
-                                               $qpart = "auth_pass = '$auth_pass'";
-                                               break;
-
-                                       case "private":
-                                               $qpart = "private = $private";
-                                               break;
-
-                                       case "include_in_digest":
-                                               $qpart = "include_in_digest = $include_in_digest";
-                                               break;
-
-                                       case "always_display_enclosures":
-                                               $qpart = "always_display_enclosures = $always_display_enclosures";
-                                               break;
-
-                                       case "mark_unread_on_update":
-                                               $qpart = "mark_unread_on_update = $mark_unread_on_update";
-                                               break;
-
-                                       case "update_on_checksum_change":
-                                               $qpart = "update_on_checksum_change = $update_on_checksum_change";
-                                               break;
-
-                                       case "cache_images":
-                                               $qpart = "cache_images = $cache_images";
-                                               break;
-
-                                       case "rtl_content":
-                                               $qpart = "rtl_content = $rtl_content";
-                                               break;
-
-                                       case "update_method":
-                                               $qpart = "update_method = '$update_method'";
-                                               break;
-
-                                       case "cat_id":
-                                               $qpart = $category_qpart_nocomma;
-                                               break;
-
-                               }
-
-                               if ($qpart) {
-                                       db_query($this->link,
-                                               "UPDATE ttrss_feeds SET $qpart WHERE id IN ($feed_ids)
-                                               AND owner_uid = " . $_SESSION["uid"]);
-                                       print "<br/>";
-                               }
-                       }
-
-                       db_query($this->link, "COMMIT");
-               }
-               return;
-       }
-
-       function resetPubSub() {
-
-               $ids = db_escape_string($_REQUEST["ids"]);
-
-               db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0 WHERE id IN ($ids)
-                       AND owner_uid = " . $_SESSION["uid"]);
-
-               return;
-       }
-
-       function remove() {
-
-               $ids = split(",", db_escape_string($_REQUEST["ids"]));
-
-               foreach ($ids as $id) {
-                       remove_feed($this->link, $id, $_SESSION["uid"]);
-               }
-
-               return;
-       }
-
-       function clear() {
-               $id = db_escape_string($_REQUEST["id"]);
-               clear_feed_articles($this->link, $id);
-       }
-
-       function rescore() {
-               $ids = split(",", db_escape_string($_REQUEST["ids"]));
-
-               foreach ($ids as $id) {
-
-                       $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
-
-                       $result = db_query($this->link, "SELECT
-                               title, content, link, ref_id, author,".
-                               SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
-                               FROM
-                                       ttrss_user_entries, ttrss_entries
-                                       WHERE ref_id = id AND feed_id = '$id' AND
-                                               owner_uid = " .$_SESSION['uid']."
-                                       ");
-
-                       $scores = array();
-
-                       while ($line = db_fetch_assoc($result)) {
-
-                               $tags = get_article_tags($this->link, $line["ref_id"]);
-
-                               $article_filters = get_article_filters($filters, $line['title'],
-                                       $line['content'], $line['link'], strtotime($line['updated']),
-                                       $line['author'], $tags);
-
-                               $new_score = calculate_article_score($article_filters);
-
-                               if (!$scores[$new_score]) $scores[$new_score] = array();
-
-                               array_push($scores[$new_score], $line['ref_id']);
-                       }
-
-                       foreach (array_keys($scores) as $s) {
-                               if ($s > 1000) {
-                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
-                                               marked = true WHERE
-                                               ref_id IN (" . join(',', $scores[$s]) . ")");
-                               } else if ($s < -500) {
-                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
-                                               unread = false WHERE
-                                               ref_id IN (" . join(',', $scores[$s]) . ")");
-                               } else {
-                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
-                                               ref_id IN (" . join(',', $scores[$s]) . ")");
-                               }
-                       }
-               }
-
-               print __("All done.");
-
-       }
-
-       function rescoreAll() {
-
-               $result = db_query($this->link,
-                       "SELECT id FROM ttrss_feeds WHERE owner_uid = " . $_SESSION['uid']);
-
-               while ($feed_line = db_fetch_assoc($result)) {
-
-                       $id = $feed_line["id"];
-
-                       $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
-
-                       $tmp_result = db_query($this->link, "SELECT
-                               title, content, link, ref_id, author,".
-                                       SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
-                                       FROM
-                                       ttrss_user_entries, ttrss_entries
-                                       WHERE ref_id = id AND feed_id = '$id' AND
-                                               owner_uid = " .$_SESSION['uid']."
-                                       ");
-
-                       $scores = array();
-
-                       while ($line = db_fetch_assoc($tmp_result)) {
-
-                               $tags = get_article_tags($this->link, $line["ref_id"]);
-
-                               $article_filters = get_article_filters($filters, $line['title'],
-                                       $line['content'], $line['link'], strtotime($line['updated']),
-                                       $line['author'], $tags);
-
-                               $new_score = calculate_article_score($article_filters);
-
-                               if (!$scores[$new_score]) $scores[$new_score] = array();
-
-                               array_push($scores[$new_score], $line['ref_id']);
-                       }
-
-                       foreach (array_keys($scores) as $s) {
-                               if ($s > 1000) {
-                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
-                                               marked = true WHERE
-                                               ref_id IN (" . join(',', $scores[$s]) . ")");
-                               } else {
-                                       db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
-                                               ref_id IN (" . join(',', $scores[$s]) . ")");
-                               }
-                       }
-               }
-
-               print __("All done.");
-
-       }
-
-       function add() {
-               $feed_url = db_escape_string(trim($_REQUEST["feed_url"]));
-               $cat_id = db_escape_string($_REQUEST["cat_id"]);
-               $p_from = db_escape_string($_REQUEST["from"]);
-
-               /* only read authentication information from POST */
-
-               $auth_login = db_escape_string(trim($_POST["auth_login"]));
-               $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
-
-               if ($p_from != 'tt-rss') {
-                       header('Content-Type: text/html; charset=utf-8');
-                       print "<html>
-                               <head>
-                                       <title>Tiny Tiny RSS</title>
-                                       <link rel=\"stylesheet\" type=\"text/css\" href=\"utility.css\">
-                                       <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
-                               </head>
-                               <body>
-                               <img class=\"floatingLogo\" src=\"images/logo_wide.png\"
-                                       alt=\"Tiny Tiny RSS\"/>
-                               <h1>Subscribe to feed...</h1>";
-               }
-
-               $rc = subscribe_to_feed($this->link, $feed_url, $cat_id, $auth_login, $auth_pass);
-
-               switch ($rc) {
-               case 1:
-                       print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
-                       break;
-               case 2:
-                       print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
-                       break;
-               case 3:
-                       print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
-                       break;
-               case 0:
-                       print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
-                       break;
-               case 4:
-                       print_notice(__("Multiple feed URLs found."));
-
-                       $feed_urls = get_feeds_from_html($feed_url);
-                       break;
-               case 5:
-                       print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
-                       break;
-               }
-
-               if ($p_from != 'tt-rss') {
-
-                       if ($feed_urls) {
-
-                               print "<form action=\"backend.php\">";
-                               print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
-                               print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
-                               print "<input type=\"hidden\" name=\"method\" value=\"add\">";
-
-                               print "<select name=\"feed_url\">";
-
-                               foreach ($feed_urls as $url => $name) {
-                                       $url = htmlspecialchars($url);
-                                       $name = htmlspecialchars($name);
-
-                                       print "<option value=\"$url\">$name</option>";
-                               }
-
-                               print "<input type=\"submit\" value=\"".__("Subscribe to selected feed").
-                                       "\">";
-
-                               print "</form>";
-                       }
-
-                       $tp_uri = get_self_url_prefix() . "/prefs.php";
-                       $tt_uri = get_self_url_prefix();
-
-                       if ($rc <= 2){
-                               $result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
-                                       feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
-
-                               $feed_id = db_fetch_result($result, 0, "id");
-                       } else {
-                               $feed_id = 0;
-                       }
-                       print "<p>";
-
-                       if ($feed_id) {
-                               print "<form method=\"GET\" style='display: inline'
-                                       action=\"$tp_uri\">
-                                       <input type=\"hidden\" name=\"tab\" value=\"feedConfig\">
-                                       <input type=\"hidden\" name=\"method\" value=\"editFeed\">
-                                       <input type=\"hidden\" name=\"methodparam\" value=\"$feed_id\">
-                                       <input type=\"submit\" value=\"".__("Edit subscription options")."\">
-                                       </form>";
-                       }
-
-                       print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
-                               <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
-                               </form></p>";
-
-                       print "</body></html>";
-                       return;
-               }
-       }
-
-       function categorize() {
-               $ids = split(",", db_escape_string($_REQUEST["ids"]));
-
-               $cat_id = db_escape_string($_REQUEST["cat_id"]);
-
-               if ($cat_id == 0) {
-                       $cat_id_qpart = 'NULL';
-               } else {
-                       $cat_id_qpart = "'$cat_id'";
-               }
-
-               db_query($this->link, "BEGIN");
-
-               foreach ($ids as $id) {
-
-                       db_query($this->link, "UPDATE ttrss_feeds SET cat_id = $cat_id_qpart
-                               WHERE id = '$id'
-                               AND owner_uid = " . $_SESSION["uid"]);
-
-               }
-
-               db_query($this->link, "COMMIT");
-       }
-
-       function removeCat() {
-               $ids = split(",", db_escape_string($_REQUEST["ids"]));
-               foreach ($ids as $id) {
-                       remove_feed_category($this->link, $id, $_SESSION["uid"]);
-               }
-       }
-
-       function addCat() {
-               $feed_cat = db_escape_string(trim($_REQUEST["cat"]));
-
-               add_feed_category($this->link, $feed_cat);
-       }
-
-       function index() {
-
-               print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
-               print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Feeds')."\">";
-
-               $result = db_query($this->link, "SELECT COUNT(id) AS num_errors
-                       FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
-
-               $num_errors = db_fetch_result($result, 0, "num_errors");
-
-               if ($num_errors > 0) {
-
-                       $error_button = "<button dojoType=\"dijit.form.Button\"
-                                       onclick=\"showFeedsWithErrors()\" id=\"errorButton\">" .
-                               __("Feeds with errors") . "</button>";
-               }
-
-               if (DB_TYPE == "pgsql") {
-                       $interval_qpart = "NOW() - INTERVAL '3 months'";
-               } else {
-                       $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
-               }
-
-               $result = db_query($this->link, "SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
-                                       (SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
-                                               ttrss_entries.id = ref_id AND
-                                                       ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
-                       ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
-
-               $num_inactive = db_fetch_result($result, 0, "num_inactive");
-
-               if ($num_inactive > 0) {
-                       $inactive_button = "<button dojoType=\"dijit.form.Button\"
-                                       onclick=\"showInactiveFeeds()\">" .
-                                       __("Inactive feeds") . "</button>";
-               }
-
-               $feed_search = db_escape_string($_REQUEST["search"]);
-
-               if (array_key_exists("search", $_REQUEST)) {
-                       $_SESSION["prefs_feed_search"] = $feed_search;
-               } else {
-                       $feed_search = $_SESSION["prefs_feed_search"];
-               }
-
-               print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
-
-               print "<div region='top' dojoType=\"dijit.Toolbar\">"; #toolbar
-
-               print "<div style='float : right; padding-right : 4px;'>
-                       <input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"
-                               value=\"$feed_search\">
-                       <button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">".
-                               __('Search')."</button>
-                       </div>";
-
-               print "<div dojoType=\"dijit.form.DropDownButton\">".
-                               "<span>" . __('Select')."</span>";
-               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
-               print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"
-                       dojoType=\"dijit.MenuItem\">".__('All')."</div>";
-               print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"
-                       dojoType=\"dijit.MenuItem\">".__('None')."</div>";
-               print "</div></div>";
-
-               print "<div dojoType=\"dijit.form.DropDownButton\">".
-                               "<span>" . __('Feeds')."</span>";
-               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
-               print "<div onclick=\"quickAddFeed()\"
-                       dojoType=\"dijit.MenuItem\">".__('Subscribe to feed')."</div>";
-               print "<div onclick=\"editSelectedFeed()\"
-                       dojoType=\"dijit.MenuItem\">".__('Edit selected feeds')."</div>";
-               print "<div onclick=\"resetFeedOrder()\"
-                       dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
-               print "<div onclick=\"batchSubscribe()\"
-                       dojoType=\"dijit.MenuItem\">".__('Batch subscribe')."</div>";
-               print "</div></div>";
-
-               if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
-                       print "<div dojoType=\"dijit.form.DropDownButton\">".
-                                       "<span>" . __('Categories')."</span>";
-                       print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
-                       print "<div onclick=\"createCategory()\"
-                               dojoType=\"dijit.MenuItem\">".__('Add category')."</div>";
-                       print "<div onclick=\"toggleHiddenFeedCats()\"
-                               dojoType=\"dijit.MenuItem\">".__('(Un)hide empty categories')."</div>";
-                       print "<div onclick=\"resetCatOrder()\"
-                               dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
-                       print "</div></div>";
-
-               }
-
-               print $error_button;
-               print $inactive_button;
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedFeeds()\">"
-                       .__('Unsubscribe')."</button dojoType=\"dijit.form.Button\"> ";
-
-               if (defined('_ENABLE_FEED_DEBUGGING')) {
-
-                       print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">
-                               <option value=\"facDefault\" selected>".__('More actions...')."</option>";
-
-                       if (FORCE_ARTICLE_PURGE == 0) {
-                               print
-                                       "<option value=\"facPurge\">".__('Manual purge')."</option>";
-                       }
-
-                       print "
-                               <option value=\"facClear\">".__('Clear feed data')."</option>
-                               <option value=\"facRescore\">".__('Rescore articles')."</option>";
-
-                       print "</select>";
-
-               }
-
-               print "</div>"; # toolbar
-
-               //print '</div>';
-               print '<div dojoType="dijit.layout.ContentPane" region="center">';
-
-               print "<div id=\"feedlistLoading\">
-               <img src='images/indicator_tiny.gif'>".
-                __("Loading, please wait...")."</div>";
-
-               print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"
-                       url=\"backend.php?op=pref-feeds&method=getfeedtree\">
-               </div>
-               <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"
-               query=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"
-                       childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
-               </div>
-               <div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"
-                       dndController=\"dijit.tree.dndSource\"
-                       betweenThreshold=\"5\"
-                       model=\"feedModel\" openOnClick=\"false\">
-               <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
-                       var id = String(item.id);
-                       var bare_id = id.substr(id.indexOf(':')+1);
-
-                       if (id.match('FEED:')) {
-                               editFeed(bare_id);
-                       } else if (id.match('CAT:')) {
-                               editCat(bare_id, item);
-                       }
-               </script>
-               <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
-                       Element.hide(\"feedlistLoading\");
-               </script>
-               </div>";
-
-#              print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">
-#                      ".__('<b>Hint:</b> you can drag feeds and categories around.')."
-#                      </div>";
-
-               print '</div>';
-               print '</div>';
-
-               print "</div>"; # feeds pane
-
-               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Import and export')."\">";
-
-               print "<h3>" . __("OPML") . "</h3>";
-
-               print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . " ";
-
-               print __("Only main settings profile can be migrated using OPML.") . "</p>";
-
-               print "<iframe id=\"upload_iframe\"
-                       name=\"upload_iframe\" onload=\"opmlImportComplete(this)\"
-                       style=\"width: 400px; height: 100px; display: none;\"></iframe>";
-
-               print "<form  name=\"opml_form\" style='display : block' target=\"upload_iframe\"
-                       enctype=\"multipart/form-data\" method=\"POST\"
-                       action=\"backend.php\">
-                       <input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;
-                       <input type=\"hidden\" name=\"op\" value=\"dlg\">
-                       <input type=\"hidden\" name=\"method\" value=\"importOpml\">
-                       <button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" .
-                       __('Import my OPML') . "</button>";
-
-               print "<hr>";
-
-               print "<p>" . __('Filename:') .
-            " <input type=\"text\" id=\"filename\" value=\"TinyTinyRSS.opml\" />&nbsp;" .
-                               __('Include settings') . "<input type=\"checkbox\" id=\"settings\" checked=\"1\"/>";
-
-               print "</p><button dojoType=\"dijit.form.Button\"
-                       onclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" .
-              __('Export OPML') . "</button></p></form>";
-
-               print "<hr>";
-
-               print "<p>".__('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . " ";
-
-               print __("Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.") . "</p>";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('pubOPMLUrl')\">".
-                       __('Display published OPML URL')."</button> ";
-
-
-               print "<h3>" . __("Article archive") . "</h3>";
-
-               print "<p>" . __("You can export and import your Starred and Archived articles for safekeeping or when migrating between tt-rss instances.") . "</p>";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return exportData()\">".
-                       __('Export my data')."</button> ";
-
-               print "<hr>";
-
-               print "<iframe id=\"data_upload_iframe\"
-                       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\">&nbsp;
-                       <input type=\"hidden\" name=\"op\" value=\"dlg\">
-                       <input type=\"hidden\" name=\"method\" value=\"dataimport\">
-                       <button dojoType=\"dijit.form.Button\" onclick=\"return importData();\" type=\"submit\">" .
-                       __('Import') . "</button>";
-
-
-               print "</div>"; # pane
-
-               if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
-
-                       print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Firefox integration')."\">";
-
-                       print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>";
-
-                       print "<p>";
-
-                       print "<button onclick='window.navigator.registerContentHandler(" .
-                      "\"application/vnd.mozilla.maybe.feed\", " .
-                      "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" .
-                                                        __('Click here to register this site as a feed reader.') .
-                               "</button>";
-
-                       print "</p>";
-
-                       print "</div>"; # pane
-               }
-
-               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Subscribing using bookmarklet')."\">";
-
-               print "<p>" . __("Drag the link below to your browser toolbar, open the feed you're interested in in your browser and click on the link to subscribe to it.") . "</p>";
-
-               $bm_subscribe_url = str_replace('%s', '', add_feed_url());
-
-               $confirm_str = str_replace("'", "\'", __('Subscribe to %s in Tiny Tiny RSS?'));
-
-               $bm_url = htmlspecialchars("javascript:{if(confirm('$confirm_str'.replace('%s',window.location.href)))window.location.href='$bm_subscribe_url'+window.location.href}");
-
-               print "<a href=\"$bm_url\" class='bookmarklet'>" . __('Subscribe in Tiny Tiny RSS'). "</a>";
-
-               print "</div>"; #pane
-
-               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Published & shared articles / Generated feeds')."\">";
-
-               print "<h3>" . __("Published articles and generated feeds") . "</h3>";
-
-               print "<p>".__('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.')."</p>";
-
-               $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() .
-                               "/public.php?op=rss&id=-2&view-mode=all_articles");;
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('generatedFeed', '$rss_url')\">".
-                       __('Display URL')."</button> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">".
-                       __('Clear all generated URLs')."</button> ";
-
-               print "<h3>" . __("Articles shared by URL") . "</h3>";
-
-               print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">".
-                       __('Unshare all articles')."</button> ";
-
-               print "</div>"; #pane
-
-               if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
-
-                       print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Twitter')."\">";
-
-                       $result = db_query($this->link, "SELECT COUNT(*) AS cid FROM ttrss_users
-                               WHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND
-                               id = " . $_SESSION['uid']);
-
-                       $is_registered = db_fetch_result($result, 0, "cid") != 0;
-
-                       if (!$is_registered) {
-                               print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
-                       } else {
-                               print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
-                       }
-
-                       print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">".
-                               __("Register with Twitter.com")."</button>";
-
-                       print " ";
-
-                       print "<button dojoType=\"dijit.form.Button\"
-                               onclick=\"return clearTwitterCredentials()\">".
-                               __("Clear stored credentials")."</button>";
-
-                       print "</div>"; # pane
-
-               }
-
-               print "</div>"; #container
-
-       }
-
-       private function feedlist_init_cat($cat_id, $hidden = false) {
-               $obj = array();
-               $cat_id = (int) $cat_id;
-
-               if ($cat_id > 0) {
-                       $cat_unread = ccache_find($this->link, $cat_id, $_SESSION["uid"], true);
-               } else if ($cat_id == 0 || $cat_id == -2) {
-                       $cat_unread = getCategoryUnread($this->link, $cat_id);
-               }
-
-               $obj['id'] = 'CAT:' . $cat_id;
-               $obj['items'] = array();
-               $obj['name'] = getCategoryTitle($this->link, $cat_id);
-               $obj['type'] = 'category';
-               $obj['unread'] = (int) $cat_unread;
-               $obj['hidden'] = $hidden;
-               $obj['bare_id'] = $cat_id;
-
-               return $obj;
-       }
-
-       private function feedlist_init_feed($feed_id, $title = false, $unread = false, $error = '', $updated = '') {
-               $obj = array();
-               $feed_id = (int) $feed_id;
-
-               if (!$title)
-                       $title = getFeedTitle($this->link, $feed_id, false);
-
-               if ($unread === false)
-                       $unread = getFeedUnread($this->link, $feed_id, false);
-
-               $obj['id'] = 'FEED:' . $feed_id;
-               $obj['name'] = $title;
-               $obj['unread'] = (int) $unread;
-               $obj['type'] = 'feed';
-               $obj['error'] = $error;
-               $obj['updated'] = $updated;
-               $obj['icon'] = getFeedIcon($feed_id);
-               $obj['bare_id'] = $feed_id;
-
-               return $obj;
-       }
-
-}
-?>
diff --git a/classes/pref_filters.php b/classes/pref_filters.php
deleted file mode 100644 (file)
index ea99d56..0000000
+++ /dev/null
@@ -1,657 +0,0 @@
-<?php
-class Pref_Filters extends Protected_Handler {
-
-       function csrf_ignore($method) {
-               $csrf_ignored = array("index", "getfiltertree", "edit");
-
-               return array_search($method, $csrf_ignored) !== false;
-       }
-
-       function filter_test($filter_type, $reg_exp,
-                       $action_id, $action_param, $filter_param, $inverse, $feed_id, $cat_id,
-                       $cat_filter) {
-
-               $result = db_query($this->link, "SELECT name FROM ttrss_filter_types WHERE
-                       id = " . $filter_type);
-               $type_name = db_fetch_result($result, 0, "name");
-
-               $result = db_query($this->link, "SELECT name FROM ttrss_filter_actions WHERE
-                       id = " . $action_id);
-               $action_name = db_fetch_result($result, 0, "name");
-
-               $filter["reg_exp"] = $reg_exp;
-               $filter["action"] = $action_name;
-               $filter["type"] = $type_name;
-               $filter["action_param"] = $action_param;
-               $filter["filter_param"] = $filter_param;
-               $filter["inverse"] = $inverse;
-
-               $filters[$type_name] = array($filter);
-
-               if ($feed_id)
-                       $feed = $feed_id;
-               else
-                       $feed = -4;
-
-               $regexp_valid = preg_match('/' . $filter['reg_exp'] . '/',
-                       $filter['reg_exp']) !== FALSE;
-
-               print __("Articles matching this filter:");
-
-               print "<div class=\"filterTestHolder\">";
-               print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
-
-               if ($regexp_valid) {
-
-                       $feed_title = getFeedTitle($this->link, $feed);
-
-                       $qfh_ret = queryFeedHeadlines($this->link, $cat_filter ? $cat_id : $feed,
-                               30, "", $cat_filter, false, false,
-                               false, "date_entered DESC", 0, $_SESSION["uid"], $filter);
-
-                       $result = $qfh_ret[0];
-
-                       $articles = array();
-                       $found = 0;
-
-                       while ($line = db_fetch_assoc($result)) {
-
-                               $entry_timestamp = strtotime($line["updated"]);
-                               $entry_tags = get_article_tags($this->link, $line["id"], $_SESSION["uid"]);
-
-                               $content_preview = truncate_string(
-                                       strip_tags($line["content_preview"]), 100, '...');
-
-                               if ($line["feed_title"])
-                                       $feed_title = $line["feed_title"];
-
-                               print "<tr>";
-
-                               print "<td width='5%' align='center'><input
-                                       dojoType=\"dijit.form.CheckBox\" checked=\"1\"
-                                       disabled=\"1\" type=\"checkbox\"></td>";
-                               print "<td>";
-
-                               print $line["title"];
-                               print "&nbsp;(";
-                               print "<b>" . $feed_title . "</b>";
-                               print "):&nbsp;";
-                               print "<span class=\"insensitive\">" . $content_preview . "</span>";
-                               print " " . mb_substr($line["date_entered"], 0, 16);
-
-                               print "</td></tr>";
-
-                               $found++;
-                       }
-
-                       if ($found == 0) {
-                               print "<tr><td align='center'>" .
-                                       __("No articles matching this filter has been found.") . "</td></tr>";
-                       }
-               } else {
-                       print "<tr><td align='center' class='error'>" .
-                               __("Invalid regular expression.") . "</td></tr>";
-
-               }
-
-               print "</table>";
-               print "</div>";
-
-       }
-
-       function getfiltertree() {
-               $root = array();
-               $root['id'] = 'root';
-               $root['name'] = __('Filters');
-               $root['items'] = array();
-
-               $search = $_SESSION["prefs_filter_search"];
-
-               if ($search) $search_qpart = " (LOWER(reg_exp) LIKE LOWER('%$search%')
-                       OR LOWER(ttrss_feeds.title) LIKE LOWER('%$search%')
-                       OR LOWER(COALESCE(ttrss_feed_categories.title, '".__('Uncategorized')."'))
-                               LIKE LOWER('%$search%') AND cat_filter = true) AND ";
-
-               $result = db_query($this->link, "SELECT
-                               ttrss_filters.id AS id,reg_exp,
-                               ttrss_filter_types.name AS filter_type_name,
-                               ttrss_filter_types.description AS filter_type_descr,
-                               enabled,
-                               inverse,
-                               cat_filter,
-                               feed_id,
-                               ttrss_filters.cat_id,
-                               action_id,
-                               filter_param,
-                               filter_type,
-                               ttrss_filter_actions.description AS action_description,
-                               ttrss_feeds.title AS feed_title,
-                               COALESCE(ttrss_feed_categories.title, '".__('Uncategorized')."') AS cat_title,
-                               ttrss_filter_actions.name AS action_name,
-                               ttrss_filters.action_param AS action_param
-                       FROM
-                               ttrss_filter_types,ttrss_filter_actions,ttrss_filters LEFT JOIN
-                                       ttrss_feeds ON (ttrss_filters.feed_id = ttrss_feeds.id) LEFT JOIN
-                                       ttrss_feed_categories ON (ttrss_filters.cat_id = ttrss_feed_categories.id)
-                       WHERE
-                               filter_type = ttrss_filter_types.id AND
-                               ttrss_filter_actions.id = action_id AND
-                               $search_qpart
-                               ttrss_filters.owner_uid = ".$_SESSION["uid"]."
-                       ORDER by action_description, reg_exp");
-
-               $cat = false;
-               $cur_action_description = "";
-
-               if (db_num_rows($result) > 0) {
-
-                       while ($line = db_fetch_assoc($result)) {
-                               if ($cur_action_description != $line['action_description']) {
-
-                                       if ($cat)
-                                               array_push($root['items'], $cat);
-
-                                       $cat = array();
-                                       $cat['id'] = 'ACTION:' . $line['action_id'];
-                                       $cat['name'] = $line['action_description'];
-                                       $cat['items'] = array();
-
-                                       $cur_action_description = $line['action_description'];
-                               }
-
-                               if (array_search($line["action_name"],
-                                       array("score", "tag", "label")) === false) {
-
-                                               $line["action_param"] = '';
-                               } else {
-                                       if ($line['action_name'] == 'label') {
-
-                                               $tmp_result = db_query($this->link, "SELECT fg_color, bg_color
-                                                       FROM ttrss_labels2 WHERE caption = '".
-                                                               db_escape_string($line["action_param"])."' AND
-                                                               owner_uid = " . $_SESSION["uid"]);
-
-                                               if (db_num_rows($tmp_result) != 0) {
-                                                       $fg_color = db_fetch_result($tmp_result, 0, "fg_color");
-                                                       $bg_color = db_fetch_result($tmp_result, 0, "bg_color");
-
-                                                       $tmp = "<span class=\"labelColorIndicator\" style='color : $fg_color; background-color : $bg_color'>&alpha;</span> " . $line['action_param'];
-
-                                                       $line['action_param'] = $tmp;
-                                               }
-                                       }
-                               }
-
-                               $filter = array();
-                               $filter['id'] = 'FILTER:' . $line['id'];
-                               $filter['bare_id'] = $line['id'];
-                               $filter['name'] = $line['reg_exp'];
-                               $filter['type'] = $line['filter_type'];
-                               $filter['enabled'] = sql_bool_to_bool($line['enabled']);
-                               $filter['param'] = $line['action_param'];
-                               $filter['inverse'] = sql_bool_to_bool($line['inverse']);
-                               $filter['checkbox'] = false;
-
-                               if (sql_bool_to_bool($line['cat_filter']))
-                                       if ($line['cat_id'] != 0) {
-                                               $filter['feed'] = $line['cat_title'];
-                                       } else {
-                                               $filter['feed'] = __('Uncategorized');
-                                       }
-                               else if ($line['feed_id'])
-                                       $filter['feed'] = $line['feed_title'];
-
-                               array_push($cat['items'], $filter);
-                       }
-
-                       array_push($root['items'], $cat);
-               }
-
-               $fl = array();
-               $fl['identifier'] = 'id';
-               $fl['label'] = 'name';
-               $fl['items'] = array($root);
-
-               print json_encode($fl);
-               return;
-       }
-
-       function edit() {
-
-               $filter_id = db_escape_string($_REQUEST["id"]);
-
-               $result = db_query($this->link,
-                       "SELECT * FROM ttrss_filters WHERE id = '$filter_id' AND owner_uid = " . $_SESSION["uid"]);
-
-               $reg_exp = htmlspecialchars(db_fetch_result($result, 0, "reg_exp"));
-               $filter_type = db_fetch_result($result, 0, "filter_type");
-               $feed_id = db_fetch_result($result, 0, "feed_id");
-               $cat_id = db_fetch_result($result, 0, "cat_id");
-               $action_id = db_fetch_result($result, 0, "action_id");
-               $action_param = db_fetch_result($result, 0, "action_param");
-               $filter_param = db_fetch_result($result, 0, "filter_param");
-
-               $enabled = sql_bool_to_bool(db_fetch_result($result, 0, "enabled"));
-               $inverse = sql_bool_to_bool(db_fetch_result($result, 0, "inverse"));
-               $cat_filter = sql_bool_to_bool(db_fetch_result($result, 0, "cat_filter"));
-
-               print "<form id=\"filter_edit_form\" onsubmit='return false'>";
-
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-filters\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$filter_id\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"editSave\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"csrf_token\" value=\"".$_SESSION['csrf_token']."\">";
-
-               $result = db_query($this->link, "SELECT id,description
-                       FROM ttrss_filter_types ORDER BY description");
-
-               $filter_types = array();
-
-               while ($line = db_fetch_assoc($result)) {
-                       //array_push($filter_types, $line["description"]);
-                       $filter_types[$line["id"]] = __($line["description"]);
-               }
-
-               print "<div class=\"dlgSec\">".__("Match")."</div>";
-
-               print "<div class=\"dlgSecCont\">";
-
-               if ($filter_type != 5) {
-                       $date_ops_invisible = 'style="display : none"';
-               }
-
-               print "<span id=\"filterDlg_dateModBox\" $date_ops_invisible>";
-               print __("Date") . " ";
-
-               $filter_params = array(
-                       "before" => __("before"),
-                       "after" => __("after"));
-
-               print_select_hash("filter_date_modifier", $filter_param,
-                       $filter_params, 'dojoType="dijit.form.Select"');
-
-               print "&nbsp;</span>";
-
-               print "<input dojoType=\"dijit.form.ValidationTextBox\"
-                                required=\"1\"
-                                name=\"reg_exp\" style=\"font-size : 16px;\" value=\"$reg_exp\">";
-
-               print "<span id=\"filterDlg_dateChkBox\" $date_ops_invisible>";
-               print "&nbsp;<button dojoType=\"dijit.form.Button\" onclick=\"return filterDlgCheckDate()\">".
-                       __('Check it')."</button>";
-               print "</span>";
-
-               print "<hr/> " . __("on field") . " ";
-               print_select_hash("filter_type", $filter_type, $filter_types,
-                       'onchange="filterDlgCheckType(this)" dojoType="dijit.form.Select"');
-
-               print "<hr/>";
-
-               print __("in") . " ";
-
-               $hidden = $cat_filter ? "style='display:none'" : "";
-
-               print "<span id='filterDlg_feeds' $hidden>";
-               print_feed_select($this->link, "feed_id", $feed_id,
-                       'dojoType="dijit.form.FilteringSelect"');
-               print "</span>";
-
-               $hidden = $cat_filter ? "" : "style='display:none'";
-
-               print "<span id='filterDlg_cats' $hidden>";
-               print_feed_cat_select($this->link, "cat_id", $cat_id,
-                       'dojoType="dijit.form.FilteringSelect"');
-               print "</span>";
-
-
-               print "</div>";
-
-               print "<div class=\"dlgSec\">".__("Perform Action")."</div>";
-
-               print "<div class=\"dlgSecCont\">";
-
-               print "<select name=\"action_id\" dojoType=\"dijit.form.Select\"
-                       onchange=\"filterDlgCheckAction(this)\">";
-
-               $result = db_query($this->link, "SELECT id,description FROM ttrss_filter_actions
-                       ORDER BY name");
-
-               while ($line = db_fetch_assoc($result)) {
-                       $is_sel = ($line["id"] == $action_id) ? "selected=\"1\"" : "";
-                       printf("<option value='%d' $is_sel>%s</option>", $line["id"], __($line["description"]));
-               }
-
-               print "</select>";
-
-               $param_hidden = ($action_id == 4 || $action_id == 6 || $action_id == 7) ? "" : "display : none";
-
-               print "<span id=\"filterDlg_paramBox\" style=\"$param_hidden\">";
-               print " " . __("with parameters:") . " ";
-
-               $param_int_hidden = ($action_id != 7) ? "" : "display : none";
-
-               print "<input style=\"$param_int_hidden\"
-                               dojoType=\"dijit.form.TextBox\" id=\"filterDlg_actionParam\"
-                               name=\"action_param\" value=\"$action_param\">";
-
-               $param_int_hidden = ($action_id == 7) ? "" : "display : none";
-
-               print_label_select($this->link, "action_param_label", $action_param,
-                "style=\"$param_int_hidden\"" .
-                'id="filterDlg_actionParamLabel" dojoType="dijit.form.Select"');
-
-               print "</span>";
-
-               print "&nbsp;"; // tiny layout hack
-
-               print "</div>";
-
-               print "<div class=\"dlgSec\">".__("Options")."</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               print "<div style=\"line-height : 100%\">";
-
-               if ($enabled) {
-                       $checked = "checked=\"1\"";
-               } else {
-                       $checked = "";
-               }
-
-               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"enabled\" id=\"enabled\" $checked>
-                               <label for=\"enabled\">".__('Enabled')."</label><hr/>";
-
-               if ($inverse) {
-                       $checked = "checked=\"1\"";
-               } else {
-                       $checked = "";
-               }
-
-               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"inverse\" id=\"inverse\" $checked>
-                       <label for=\"inverse\">".__('Inverse match')."</label><hr/>";
-
-               if ($cat_filter) {
-                       $checked = "checked=\"1\"";
-               } else {
-                       $checked = "";
-               }
-
-               print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"cat_filter\" id=\"cat_filter\" onchange=\"filterDlgCheckCat(this)\" $checked>
-                               <label for=\"cat_filter\">".__('Apply to category')."</label><hr/>";
-
-               print "</div>";
-               print "</div>";
-
-               print "<div class=\"dlgButtons\">";
-
-               print "<div style=\"float : left\">";
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').removeFilter()\">".
-                       __('Remove')."</button>";
-               print "</div>";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').test()\">".
-                       __('Test')."</button> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').execute()\">".
-                       __('Save')."</button> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').hide()\">".
-                       __('Cancel')."</button>";
-
-               print "</div>";
-       }
-
-       function editSave() {
-
-               $savemode = db_escape_string($_REQUEST["savemode"]);
-               $reg_exp = db_escape_string(trim($_REQUEST["reg_exp"]));
-               $filter_type = db_escape_string(trim($_REQUEST["filter_type"]));
-               $filter_id = db_escape_string($_REQUEST["id"]);
-               $feed_id = db_escape_string($_REQUEST["feed_id"]);
-               $action_id = db_escape_string($_REQUEST["action_id"]);
-               $action_param = db_escape_string($_REQUEST["action_param"]);
-               $action_param_label = db_escape_string($_REQUEST["action_param_label"]);
-               $enabled = checkbox_to_sql_bool(db_escape_string($_REQUEST["enabled"]));
-               $inverse = checkbox_to_sql_bool(db_escape_string($_REQUEST["inverse"]));
-               $cat_filter = checkbox_to_sql_bool(db_escape_string($_REQUEST["cat_filter"]));
-               $cat_id = db_escape_string($_REQUEST['cat_id']);
-
-               # for the time being, no other filters use params anyway...
-               $filter_param = db_escape_string($_REQUEST["filter_date_modifier"]);
-
-               if (!$feed_id) {
-                       $feed_id = 'NULL';
-               } else {
-                       $feed_id = sprintf("'%s'", db_escape_string($feed_id));
-               }
-
-               if (!$cat_id) {
-                       $cat_id = 'NULL';
-               } else {
-                       $cat_id = sprintf("'%d'", db_escape_string($cat_id));
-               }
-
-               /* When processing 'assign label' filters, action_param_label dropbox
-                * overrides action_param */
-
-               if ($action_id == 7) {
-                       $action_param = $action_param_label;
-               }
-
-               if ($action_id == 6) {
-                       $action_param = (int) str_replace("+", "", $action_param);
-               }
-
-               if ($savemode != "test") {
-                       $result = db_query($this->link, "UPDATE ttrss_filters SET
-                               reg_exp = '$reg_exp',
-                               feed_id = $feed_id,
-                               cat_id = $cat_id,
-                               action_id = '$action_id',
-                               filter_type = '$filter_type',
-                               enabled = $enabled,
-                               inverse = $inverse,
-                               cat_filter = $cat_filter,
-                               action_param = '$action_param',
-                               filter_param = '$filter_param'
-                               WHERE id = '$filter_id' AND owner_uid = " . $_SESSION["uid"]);
-               } else {
-
-                       $this->filter_test($filter_type, $reg_exp,
-                               $action_id, $action_param, $filter_param, sql_bool_to_bool($inverse),
-                               (int) $_REQUEST["feed_id"], (int) $_REQUEST['cat_id'],
-                               sql_bool_to_bool($cat_filter));
-
-                       print "<div align='center'>";
-                       print "<button dojoType=\"dijit.form.Button\"
-                               onclick=\"return dijit.byId('filterTestDlg').hide()\">".
-                               __('Close this window')."</button>";
-                       print "</div>";
-
-               }
-       }
-
-       function remove() {
-
-               $ids = split(",", db_escape_string($_REQUEST["ids"]));
-
-               foreach ($ids as $id) {
-                       db_query($this->link, "DELETE FROM ttrss_filters WHERE id = '$id' AND owner_uid = ". $_SESSION["uid"]);
-               }
-       }
-
-       function add() {
-
-               $savemode = db_escape_string($_REQUEST["savemode"]);
-               $regexp = db_escape_string(trim($_REQUEST["reg_exp"]));
-               $filter_type = db_escape_string(trim($_REQUEST["filter_type"]));
-               $feed_id = db_escape_string($_REQUEST["feed_id"]);
-               $cat_id = db_escape_string($_REQUEST["cat_id"]);
-               $action_id = db_escape_string($_REQUEST["action_id"]);
-               $action_param = db_escape_string($_REQUEST["action_param"]);
-               $action_param_label = db_escape_string($_REQUEST["action_param_label"]);
-               $inverse = checkbox_to_sql_bool(db_escape_string($_REQUEST["inverse"]));
-               $cat_filter = checkbox_to_sql_bool(db_escape_string($_REQUEST["cat_filter"]));
-
-               # for the time being, no other filters use params anyway...
-               $filter_param = db_escape_string($_REQUEST["filter_date_modifier"]);
-
-               if (!$regexp) return;
-
-               if (!$feed_id) {
-                       $feed_id = 'NULL';
-               } else {
-                       $feed_id = sprintf("'%s'", db_escape_string($feed_id));
-               }
-
-               if (!$cat_id) {
-                       $cat_id = 'NULL';
-               } else {
-                       $cat_id = sprintf("'%d'", db_escape_string($cat_id));
-               }
-
-               /* When processing 'assign label' filters, action_param_label dropbox
-                * overrides action_param */
-
-               if ($action_id == 7) {
-                       $action_param = $action_param_label;
-               }
-
-               if ($action_id == 6) {
-                       $action_param = (int) str_replace("+", "", $action_param);
-               }
-
-               if ($savemode != "test") {
-                       $result = db_query($this->link,
-                               "INSERT INTO ttrss_filters (reg_exp,filter_type,owner_uid,feed_id,
-                                       action_id, action_param, inverse, filter_param, cat_id, cat_filter)
-                               VALUES
-                                       ('$regexp', '$filter_type','".$_SESSION["uid"]."',
-                                       $feed_id, '$action_id', '$action_param', $inverse,
-                                       '$filter_param', $cat_id, $cat_filter)");
-
-                       if (db_affected_rows($this->link, $result) != 0) {
-                               print T_sprintf("Created filter <b>%s</b>", htmlspecialchars($regexp));
-                       }
-
-               } else {
-
-                       $this->filter_test($filter_type, $regexp,
-                               $action_id, $action_param, $filter_param, sql_bool_to_bool($inverse),
-                               (int) $_REQUEST["feed_id"], (int) $_REQUEST['cat_id'],
-                               sql_bool_to_bool($cat_filter));
-
-                       print "<div align='center'>";
-                       print "<button dojoType=\"dijit.form.Button\"
-                               onclick=\"return dijit.byId('filterTestDlg').hide()\">".
-                               __('Close this window')."</button>";
-                       print "</div>";
-
-               }
-       }
-
-       function index() {
-
-               $sort = db_escape_string($_REQUEST["sort"]);
-
-               if (!$sort || $sort == "undefined") {
-                       $sort = "reg_exp";
-               }
-
-               $result = db_query($this->link, "SELECT id,description
-                       FROM ttrss_filter_types ORDER BY description");
-
-               $filter_types = array();
-
-               while ($line = db_fetch_assoc($result)) {
-                       //array_push($filter_types, $line["description"]);
-                       $filter_types[$line["id"]] = $line["description"];
-               }
-
-
-               $filter_search = db_escape_string($_REQUEST["search"]);
-
-               if (array_key_exists("search", $_REQUEST)) {
-                       $_SESSION["prefs_filter_search"] = $filter_search;
-               } else {
-                       $filter_search = $_SESSION["prefs_filter_search"];
-               }
-
-               print "<div id=\"pref-filter-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
-               print "<div id=\"pref-filter-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
-               print "<div id=\"pref-filter-toolbar\" dojoType=\"dijit.Toolbar\">";
-
-               $filter_search = db_escape_string($_REQUEST["search"]);
-
-               if (array_key_exists("search", $_REQUEST)) {
-                       $_SESSION["prefs_filter_search"] = $filter_search;
-               } else {
-                       $filter_search = $_SESSION["prefs_filter_search"];
-               }
-
-               print "<div style='float : right; padding-right : 4px;'>
-                       <input dojoType=\"dijit.form.TextBox\" id=\"filter_search\" size=\"20\" type=\"search\"
-                               value=\"$filter_search\">
-                       <button dojoType=\"dijit.form.Button\" onclick=\"updateFilterList()\">".
-                               __('Search')."</button>
-                       </div>";
-
-               print "<div dojoType=\"dijit.form.DropDownButton\">".
-                               "<span>" . __('Select')."</span>";
-               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
-               print "<div onclick=\"dijit.byId('filterTree').model.setAllChecked(true)\"
-                       dojoType=\"dijit.MenuItem\">".__('All')."</div>";
-               print "<div onclick=\"dijit.byId('filterTree').model.setAllChecked(false)\"
-                       dojoType=\"dijit.MenuItem\">".__('None')."</div>";
-               print "</div></div>";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return quickAddFilter()\">".
-                       __('Create filter')."</button> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return editSelectedFilter()\">".
-                       __('Edit')."</button> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return removeSelectedFilters()\">".
-                       __('Remove')."</button> ";
-
-               if (defined('_ENABLE_FEED_DEBUGGING')) {
-                       print "<button dojoType=\"dijit.form.Button\" onclick=\"rescore_all_feeds()\">".
-                               __('Rescore articles')."</button> ";
-               }
-
-               print "</div>"; # toolbar
-               print "</div>"; # toolbar-frame
-               print "<div id=\"pref-filter-content\" dojoType=\"dijit.layout.ContentPane\" region=\"center\">";
-
-               print "<div id=\"filterlistLoading\">
-               <img src='images/indicator_tiny.gif'>".
-                __("Loading, please wait...")."</div>";
-
-               print "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"filterStore\"
-                       url=\"backend.php?op=pref-filters&method=getfiltertree\">
-               </div>
-               <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"filterModel\" store=\"filterStore\"
-               query=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"
-                       childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
-               </div>
-               <div dojoType=\"fox.PrefFilterTree\" id=\"filterTree\"
-                       model=\"filterModel\" openOnClick=\"true\">
-               <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
-                       Element.hide(\"filterlistLoading\");
-               </script>
-               <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
-                       var id = String(item.id);
-                       var bare_id = id.substr(id.indexOf(':')+1);
-
-                       if (id.match('FILTER:')) {
-                               editFilter(bare_id);
-                       }
-               </script>
-
-               </div>";
-
-               print "</div>"; #pane
-               print "</div>"; #container
-
-       }
-}
-?>
diff --git a/classes/pref_instances.php b/classes/pref_instances.php
deleted file mode 100644 (file)
index fec9578..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-<?php
-class Pref_Instances extends Protected_Handler {
-
-       function csrf_ignore($method) {
-               $csrf_ignored = array("index", "edit");
-
-               return array_search($method, $csrf_ignored) !== false;
-       }
-
-       function before($method) {
-               if (parent::before($method)) {
-                       if ($_SESSION["access_level"] < 10) {
-                               print __("Your access level is insufficient to open this tab.");
-                               return false;
-                       }
-                       return true;
-               }
-               return false;
-       }
-
-       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%\">&nbsp;</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('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>" . htmlspecialchars($line['num_feeds']) . "</td>";
-
-                       print "</tr>";
-
-                       ++$lnum;
-               }
-
-               print "</table>";
-
-               print "</div>"; #pane
-               print "</div>"; #container
-
-       }
-}
-?>
diff --git a/classes/pref_labels.php b/classes/pref_labels.php
deleted file mode 100644 (file)
index 951ae45..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-<?php
-class Pref_Labels extends Protected_Handler {
-
-       function csrf_ignore($method) {
-               $csrf_ignored = array("index", "getlabeltree", "edit");
-
-               return array_search($method, $csrf_ignored) !== false;
-       }
-
-       function edit() {
-               $label_id = db_escape_string($_REQUEST['id']);
-
-               $result = db_query($this->link, "SELECT * FROM ttrss_labels2 WHERE
-                       id = '$label_id' AND owner_uid = " . $_SESSION["uid"]);
-
-               $line = db_fetch_assoc($result);
-
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$label_id\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-labels\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"save\">";
-
-               print "<div class=\"dlgSec\">".__("Caption")."</div>";
-
-               print "<div class=\"dlgSecCont\">";
-
-               $fg_color = $line['fg_color'];
-               $bg_color = $line['bg_color'];
-
-               print "<span class=\"labelColorIndicator\" id=\"label-editor-indicator\" style='color : $fg_color; background-color : $bg_color; margin-bottom : 4px; margin-right : 4px'>&alpha;</span>";
-
-               print "<input style=\"font-size : 16px\" name=\"caption\"
-                       dojoType=\"dijit.form.ValidationTextBox\"
-                       required=\"true\"
-                       value=\"".htmlspecialchars($line['caption'])."\">";
-
-               print "</div>";
-               print "<div class=\"dlgSec\">" . __("Colors") . "</div>";
-               print "<div class=\"dlgSecCont\">";
-
-               print "<table cellspacing=\"0\">";
-
-               print "<tr><td>".__("Foreground:")."</td><td>".__("Background:").
-                       "</td></tr>";
-
-               print "<tr><td style='padding-right : 10px'>";
-
-               print "<input dojoType=\"dijit.form.TextBox\"
-                       style=\"display : none\" id=\"labelEdit_fgColor\"
-                       name=\"fg_color\" value=\"$fg_color\">";
-               print "<input dojoType=\"dijit.form.TextBox\"
-                       style=\"display : none\" id=\"labelEdit_bgColor\"
-                       name=\"bg_color\" value=\"$bg_color\">";
-
-               print "<div dojoType=\"dijit.ColorPalette\">
-                       <script type=\"dojo/method\" event=\"onChange\" args=\"fg_color\">
-                               dijit.byId(\"labelEdit_fgColor\").attr('value', fg_color);
-                               $('label-editor-indicator').setStyle({color: fg_color});
-                       </script>
-               </div>";
-               print "</div>";
-
-               print "</td><td>";
-
-               print "<div dojoType=\"dijit.ColorPalette\">
-                       <script type=\"dojo/method\" event=\"onChange\" args=\"bg_color\">
-                               dijit.byId(\"labelEdit_bgColor\").attr('value', bg_color);
-                               $('label-editor-indicator').setStyle({backgroundColor: bg_color});
-                       </script>
-               </div>";
-               print "</div>";
-
-               print "</td></tr></table>";
-               print "</div>";
-
-#                      print "</form>";
-
-               print "<div class=\"dlgButtons\">";
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('labelEditDlg').execute()\">".
-                       __('Save')."</button>";
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('labelEditDlg').hide()\">".
-                       __('Cancel')."</button>";
-               print "</div>";
-
-               return;
-       }
-
-       function getlabeltree() {
-               $root = array();
-               $root['id'] = 'root';
-               $root['name'] = __('Labels');
-               $root['items'] = array();
-
-               $result = db_query($this->link, "SELECT *
-                       FROM ttrss_labels2
-                       WHERE owner_uid = ".$_SESSION["uid"]."
-                       ORDER BY caption");
-
-               while ($line = db_fetch_assoc($result)) {
-                       $label = array();
-                       $label['id'] = 'LABEL:' . $line['id'];
-                       $label['bare_id'] = $line['id'];
-                       $label['name'] = $line['caption'];
-                       $label['fg_color'] = $line['fg_color'];
-                       $label['bg_color'] = $line['bg_color'];
-                       $label['type'] = 'label';
-                       $label['checkbox'] = false;
-
-                       array_push($root['items'], $label);
-               }
-
-               $fl = array();
-               $fl['identifier'] = 'id';
-               $fl['label'] = 'name';
-               $fl['items'] = array($root);
-
-               print json_encode($fl);
-               return;
-       }
-
-       function colorset() {
-               $kind = db_escape_string($_REQUEST["kind"]);
-               $ids = split(',', db_escape_string($_REQUEST["ids"]));
-               $color = db_escape_string($_REQUEST["color"]);
-               $fg = db_escape_string($_REQUEST["fg"]);
-               $bg = db_escape_string($_REQUEST["bg"]);
-
-               foreach ($ids as $id) {
-
-                       if ($kind == "fg" || $kind == "bg") {
-                               db_query($this->link, "UPDATE ttrss_labels2 SET
-                                       ${kind}_color = '$color' WHERE id = '$id'
-                                       AND owner_uid = " . $_SESSION["uid"]);
-                       } else {
-                               db_query($this->link, "UPDATE ttrss_labels2 SET
-                                       fg_color = '$fg', bg_color = '$bg' WHERE id = '$id'
-                                       AND owner_uid = " . $_SESSION["uid"]);
-                       }
-
-                       $caption = db_escape_string(label_find_caption($this->link, $id, $_SESSION["uid"]));
-
-                       /* Remove cached data */
-
-                       db_query($this->link, "UPDATE ttrss_user_entries SET label_cache = ''
-                               WHERE label_cache LIKE '%$caption%' AND owner_uid = " . $_SESSION["uid"]);
-
-               }
-
-               return;
-       }
-
-       function colorreset() {
-               $ids = split(',', db_escape_string($_REQUEST["ids"]));
-
-               foreach ($ids as $id) {
-                       db_query($this->link, "UPDATE ttrss_labels2 SET
-                               fg_color = '', bg_color = '' WHERE id = '$id'
-                               AND owner_uid = " . $_SESSION["uid"]);
-
-                       $caption = db_escape_string(label_find_caption($this->link, $id, $_SESSION["uid"]));
-
-                       /* Remove cached data */
-
-                       db_query($this->link, "UPDATE ttrss_user_entries SET label_cache = ''
-                               WHERE label_cache LIKE '%$caption%' AND owner_uid = " . $_SESSION["uid"]);
-               }
-
-       }
-
-       function save() {
-
-               $id = db_escape_string($_REQUEST["id"]);
-               $caption = db_escape_string(trim($_REQUEST["caption"]));
-
-               db_query($this->link, "BEGIN");
-
-               $result = db_query($this->link, "SELECT caption FROM ttrss_labels2
-                       WHERE id = '$id' AND owner_uid = ". $_SESSION["uid"]);
-
-               if (db_num_rows($result) != 0) {
-                       $old_caption = db_fetch_result($result, 0, "caption");
-
-                       $result = db_query($this->link, "SELECT id FROM ttrss_labels2
-                               WHERE caption = '$caption' AND owner_uid = ". $_SESSION["uid"]);
-
-                       if (db_num_rows($result) == 0) {
-                               if ($caption) {
-                                       $result = db_query($this->link, "UPDATE ttrss_labels2 SET
-                                               caption = '$caption' WHERE id = '$id' AND
-                                               owner_uid = " . $_SESSION["uid"]);
-
-                                       /* Update filters that reference label being renamed */
-
-                                       $old_caption = db_escape_string($old_caption);
-
-                                       db_query($this->link, "UPDATE ttrss_filters SET
-                                               action_param = '$caption' WHERE action_param = '$old_caption'
-                                               AND action_id = 7
-                                               AND owner_uid = " . $_SESSION["uid"]);
-
-                                       print $_REQUEST["value"];
-                               } else {
-                                       print $old_caption;
-                               }
-                       } else {
-                               print $old_caption;
-                       }
-               }
-
-               db_query($this->link, "COMMIT");
-
-               return;
-       }
-
-       function remove() {
-
-               $ids = split(",", db_escape_string($_REQUEST["ids"]));
-
-               foreach ($ids as $id) {
-                       label_remove($this->link, $id, $_SESSION["uid"]);
-               }
-
-       }
-
-       function add() {
-               $caption = db_escape_string($_REQUEST["caption"]);
-               $output = db_escape_string($_REQUEST["output"]);
-
-               if ($caption) {
-
-                       if (label_create($this->link, $caption)) {
-                               if (!$output) {
-                                       print T_sprintf("Created label <b>%s</b>", htmlspecialchars($caption));
-                               }
-                       }
-
-                       if ($output == "select") {
-                               header("Content-Type: text/xml");
-
-                               print "<rpc-reply><payload>";
-
-                               print_label_select($this->link, "select_label",
-                                       $caption, "");
-
-                               print "</payload></rpc-reply>";
-                       }
-               }
-
-               return;
-       }
-
-       function index() {
-
-               $sort = db_escape_string($_REQUEST["sort"]);
-
-               if (!$sort || $sort == "undefined") {
-                       $sort = "caption";
-               }
-
-               $label_search = db_escape_string($_REQUEST["search"]);
-
-               if (array_key_exists("search", $_REQUEST)) {
-                       $_SESSION["prefs_label_search"] = $label_search;
-               } else {
-                       $label_search = $_SESSION["prefs_label_search"];
-               }
-
-               print "<div id=\"pref-label-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
-               print "<div id=\"pref-label-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
-               print "<div id=\"pref-label-toolbar\" dojoType=\"dijit.Toolbar\">";
-
-               print "<div dojoType=\"dijit.form.DropDownButton\">".
-                               "<span>" . __('Select')."</span>";
-               print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
-               print "<div onclick=\"dijit.byId('labelTree').model.setAllChecked(true)\"
-                       dojoType=\"dijit.MenuItem\">".__('All')."</div>";
-               print "<div onclick=\"dijit.byId('labelTree').model.setAllChecked(false)\"
-                       dojoType=\"dijit.MenuItem\">".__('None')."</div>";
-               print "</div></div>";
-
-               print"<button dojoType=\"dijit.form.Button\" onclick=\"return addLabel()\">".
-                       __('Create label')."</button dojoType=\"dijit.form.Button\"> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedLabels()\">".
-                       __('Remove')."</button dojoType=\"dijit.form.Button\"> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"labelColorReset()\">".
-                       __('Clear colors')."</button dojoType=\"dijit.form.Button\">";
-
-
-               print "</div>"; #toolbar
-               print "</div>"; #pane
-               print "<div id=\"pref-label-content\" dojoType=\"dijit.layout.ContentPane\" region=\"center\">";
-
-               print "<div id=\"labellistLoading\">
-               <img src='images/indicator_tiny.gif'>".
-                __("Loading, please wait...")."</div>";
-
-               print "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"labelStore\"
-                       url=\"backend.php?op=pref-labels&method=getlabeltree\">
-               </div>
-               <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"labelModel\" store=\"labelStore\"
-               query=\"{id:'root'}\" rootId=\"root\"
-                       childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
-               </div>
-               <div dojoType=\"fox.PrefLabelTree\" id=\"labelTree\"
-                       model=\"labelModel\" openOnClick=\"true\">
-               <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
-                       Element.hide(\"labellistLoading\");
-               </script>
-               <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
-                       var id = String(item.id);
-                       var bare_id = id.substr(id.indexOf(':')+1);
-
-                       if (id.match('LABEL:')) {
-                               editLabel(bare_id);
-                       }
-               </script>
-               </div>";
-
-               print "</div>"; #pane
-               print "</div>"; #container
-
-       }
-}
-
-?>
diff --git a/classes/pref_prefs.php b/classes/pref_prefs.php
deleted file mode 100644 (file)
index 60d2411..0000000
+++ /dev/null
@@ -1,499 +0,0 @@
-<?php
-class Pref_Prefs extends Protected_Handler {
-
-       function csrf_ignore($method) {
-               $csrf_ignored = array("index");
-
-               return array_search($method, $csrf_ignored) !== false;
-       }
-
-       function changepassword() {
-
-               $old_pw = $_POST["old_password"];
-               $new_pw = $_POST["new_password"];
-               $con_pw = $_POST["confirm_password"];
-
-               if ($old_pw == "") {
-                       print "ERROR: ".__("Old password cannot be blank.");
-                       return;
-               }
-
-               if ($new_pw == "") {
-                       print "ERROR: ".__("New password cannot be blank.");
-                       return;
-               }
-
-               if ($new_pw != $con_pw) {
-                       print "ERROR: ".__("Entered passwords do not match.");
-                       return;
-               }
-
-               $module_class = "auth_" . $_SESSION["auth_module"];
-               $authenticator = new $module_class($this->link);
-
-               if (method_exists($authenticator, "change_password")) {
-                       print $authenticator->change_password($_SESSION["uid"], $old_pw, $new_pw);
-               } else {
-                       print "ERROR: ".__("Function not supported by authentication module.");
-               }
-       }
-
-       function saveconfig() {
-
-               $_SESSION["prefs_cache"] = false;
-
-               $orig_theme = get_pref($this->link, "_THEME_ID");
-
-               foreach (array_keys($_POST) as $pref_name) {
-
-                       $pref_name = db_escape_string($pref_name);
-                       $value = db_escape_string($_POST[$pref_name]);
-
-                       if ($pref_name == 'DIGEST_PREFERRED_TIME') {
-                               if (get_pref($this->link, 'DIGEST_PREFERRED_TIME') != $value) {
-
-                                       db_query($this->link, "UPDATE ttrss_users SET
-                                               last_digest_sent = NULL WHERE id = " . $_SESSION['uid']);
-
-                               }
-                       }
-
-                       set_pref($this->link, $pref_name, $value);
-
-               }
-
-               if ($orig_theme != get_pref($this->link, "_THEME_ID")) {
-                       print "PREFS_THEME_CHANGED";
-               } else {
-                       print __("The configuration was saved.");
-               }
-       }
-
-       function getHelp() {
-
-               $pref_name = db_escape_string($_REQUEST["pn"]);
-
-               $result = db_query($this->link, "SELECT help_text FROM ttrss_prefs
-                       WHERE pref_name = '$pref_name'");
-
-               if (db_num_rows($result) > 0) {
-                       $help_text = db_fetch_result($result, 0, "help_text");
-                       print $help_text;
-               } else {
-                       printf(__("Unknown option: %s"), $pref_name);
-               }
-       }
-
-       function changeemail() {
-
-               $email = db_escape_string($_POST["email"]);
-               $full_name = db_escape_string($_POST["full_name"]);
-
-               $active_uid = $_SESSION["uid"];
-
-               db_query($this->link, "UPDATE ttrss_users SET email = '$email',
-                       full_name = '$full_name' WHERE id = '$active_uid'");
-
-               print __("Your personal data has been saved.");
-
-               return;
-       }
-
-       function resetconfig() {
-
-               $_SESSION["prefs_op_result"] = "reset-to-defaults";
-
-               if ($_SESSION["profile"]) {
-                       $profile_qpart = "profile = '" . $_SESSION["profile"] . "'";
-               } else {
-                       $profile_qpart = "profile IS NULL";
-               }
-
-               db_query($this->link, "DELETE FROM ttrss_user_prefs
-                       WHERE $profile_qpart AND owner_uid = ".$_SESSION["uid"]);
-
-               initialize_user_prefs($this->link, $_SESSION["uid"], $_SESSION["profile"]);
-
-               print "PREFS_THEME_CHANGED";
-       }
-
-       function index() {
-
-               global $access_level_names;
-
-               $prefs_blacklist = array("HIDE_READ_FEEDS", "FEEDS_SORT_BY_UNREAD",
-                                       "STRIP_UNSAFE_TAGS");
-
-               $profile_blacklist = array("ALLOW_DUPLICATE_POSTS", "PURGE_OLD_DAYS",
-                                       "PURGE_UNREAD_ARTICLES", "DIGEST_ENABLE", "DIGEST_CATCHUP",
-                                       "BLACKLISTED_TAGS", "ENABLE_API_ACCESS", "UPDATE_POST_ON_CHECKSUM_CHANGE",
-                                       "DEFAULT_UPDATE_INTERVAL", "USER_TIMEZONE", "SORT_HEADLINES_BY_FEED_DATE",
-                                       "SSL_CERT_SERIAL", "DIGEST_PREFERRED_TIME");
-
-
-               $_SESSION["prefs_op_result"] = "";
-
-               print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
-               print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Personal data / Authentication')."\">";
-
-               print "<form dojoType=\"dijit.form.Form\" id=\"changeUserdataForm\">";
-
-               print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
-               evt.preventDefault();
-               if (this.validate()) {
-                       notify_progress('Saving data...', true);
-
-                       new Ajax.Request('backend.php', {
-                               parameters: dojo.objectToQuery(this.getValues()),
-                               onComplete: function(transport) {
-                                       notify_callback2(transport);
-                       } });
-
-               }
-               </script>";
-
-               print "<table width=\"100%\" class=\"prefPrefsList\">";
-
-               $result = db_query($this->link, "SELECT email,full_name,
-                       access_level FROM ttrss_users
-                       WHERE id = ".$_SESSION["uid"]);
-
-               $email = htmlspecialchars(db_fetch_result($result, 0, "email"));
-               $full_name = htmlspecialchars(db_fetch_result($result, 0, "full_name"));
-
-               print "<tr><td width=\"40%\">".__('Full name')."</td>";
-               print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" name=\"full_name\" required=\"1\"
-                       value=\"$full_name\"></td></tr>";
-
-               print "<tr><td width=\"40%\">".__('E-mail')."</td>";
-               print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" name=\"email\" required=\"1\" value=\"$email\"></td></tr>";
-
-               if (!SINGLE_USER_MODE && !$_SESSION["hide_hello"]) {
-
-                       $access_level = db_fetch_result($result, 0, "access_level");
-                       print "<tr><td width=\"40%\">".__('Access level')."</td>";
-                       print "<td>" . $access_level_names[$access_level] . "</td></tr>";
-               }
-
-               print "</table>";
-
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-prefs\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"changeemail\">";
-
-               print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
-                       __("Save data")."</button>";
-
-               print "</form>";
-
-               if  ($_SESSION["auth_module"]) {
-                       $module_class = "auth_" . $_SESSION["auth_module"];
-                       $authenticator = new $module_class($this->link);
-               } else {
-                       $authenticator = false;
-               }
-
-               if ($authenticator && method_exists($authenticator, "change_password")) {
-
-                       $result = db_query($this->link, "SELECT id FROM ttrss_users
-                               WHERE id = ".$_SESSION["uid"]." AND pwd_hash
-                               = 'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'");
-
-                       if (db_num_rows($result) != 0) {
-                               print format_warning(__("Your password is at default value, please change it."), "default_pass_warning");
-                       }
-
-                       print "<form dojoType=\"dijit.form.Form\">";
-
-                       print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
-                       evt.preventDefault();
-                       if (this.validate()) {
-                               notify_progress('Changing password...', true);
-
-                               new Ajax.Request('backend.php', {
-                                       parameters: dojo.objectToQuery(this.getValues()),
-                                       onComplete: function(transport) {
-                                               notify('');
-                                               if (transport.responseText.indexOf('ERROR: ') == 0) {
-                                                       notify_error(transport.responseText.replace('ERROR: ', ''));
-                                               } else {
-                                                       notify_info(transport.responseText);
-                                                       var warn = $('default_pass_warning');
-                                                       if (warn) Element.hide(warn);
-                                               }
-                               }});
-                               this.reset();
-                       }
-                       </script>";
-
-                       print "<table width=\"100%\" class=\"prefPrefsList\">";
-
-                       print "<tr><td width=\"40%\">".__("Old password")."</td>";
-                       print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" type=\"password\" required=\"1\" name=\"old_password\"></td></tr>";
-
-                       print "<tr><td width=\"40%\">".__("New password")."</td>";
-
-                       print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" type=\"password\" required=\"1\"
-                               name=\"new_password\"></td></tr>";
-
-                       print "<tr><td width=\"40%\">".__("Confirm password")."</td>";
-
-                       print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" type=\"password\" required=\"1\" name=\"confirm_password\"></td></tr>";
-
-                       print "</table>";
-
-                       print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-prefs\">";
-                       print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"changepassword\">";
-
-                       print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
-                               __("Change password")."</button>";
-
-                       print "</form>";
-
-               }
-
-               print "</div>"; #pane
-
-               print "<div dojoType=\"dijit.layout.AccordionPane\" selected=\"true\" title=\"".__('Preferences')."\">";
-
-               print "<form dojoType=\"dijit.form.Form\" id=\"changeSettingsForm\">";
-
-               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) {
-                                       var msg = transport.responseText;
-                                       if (msg.match('PREFS_THEME_CHANGED')) {
-                                               window.location.reload();
-                                       } else {
-                                               notify_info(msg);
-                                       }
-                       } });
-               }
-               </script>";
-
-               print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
-
-               print '<div dojoType="dijit.layout.ContentPane" region="center" style="overflow-y : auto">';
-
-               if ($_SESSION["profile"]) {
-                       print_notice("Some preferences are only available in default profile.");
-               }
-
-               if ($_SESSION["profile"]) {
-                       initialize_user_prefs($this->link, $_SESSION["uid"], $_SESSION["profile"]);
-                       $profile_qpart = "profile = '" . $_SESSION["profile"] . "'";
-               } else {
-                       initialize_user_prefs($this->link, $_SESSION["uid"]);
-                       $profile_qpart = "profile IS NULL";
-               }
-
-               $result = db_query($this->link, "SELECT DISTINCT
-                       ttrss_user_prefs.pref_name,short_desc,help_text,value,type_name,
-                       section_name,def_value,section_id
-                       FROM ttrss_prefs,ttrss_prefs_types,ttrss_prefs_sections,ttrss_user_prefs
-                       WHERE type_id = ttrss_prefs_types.id AND
-                               $profile_qpart AND
-                               section_id = ttrss_prefs_sections.id AND
-                               ttrss_user_prefs.pref_name = ttrss_prefs.pref_name AND
-                               short_desc != '' AND
-                               owner_uid = ".$_SESSION["uid"]."
-                       ORDER BY section_id,short_desc");
-
-               $lnum = 0;
-
-               $active_section = "";
-
-               while ($line = db_fetch_assoc($result)) {
-
-                       if (in_array($line["pref_name"], $prefs_blacklist)) {
-                               continue;
-                       }
-
-                       if ($_SESSION["profile"] && in_array($line["pref_name"],
-                                       $profile_blacklist)) {
-                               continue;
-                       }
-
-                       if ($active_section != $line["section_name"]) {
-
-                               if ($active_section != "") {
-                                       print "</table>";
-                               }
-
-                               print "<table width=\"100%\" class=\"prefPrefsList\">";
-
-                               $active_section = $line["section_name"];
-
-                               print "<tr><td colspan=\"3\"><h3>".__($active_section)."</h3></td></tr>";
-
-                               if ($line["section_id"] == 2) {
-                                       print "<tr><td width=\"40%\">".__("Select theme")."</td>";
-
-                                       $user_theme = get_pref($this->link, "_THEME_ID");
-                                       $themes = get_all_themes();
-
-                                       print "<td><select name=\"_THEME_ID\" dojoType=\"dijit.form.Select\">";
-                                       print "<option value='Default'>".__('Default')."</option>";
-                                       print "<option value='----------------' disabled=\"1\">--------</option>";
-
-                                       foreach ($themes as $t) {
-                                               $base = $t['base'];
-                                               $name = $t['name'];
-
-                                               if ($base == $user_theme) {
-                                                       $selected = "selected=\"1\"";
-                                               } else {
-                                                       $selected = "";
-                                               }
-
-                                               print "<option $selected value='$base'>$name</option>";
-
-                                       }
-
-                                       print "</select></td></tr>";
-                               }
-                               $lnum = 0;
-                       }
-
-                       print "<tr>";
-
-                       $type_name = $line["type_name"];
-                       $pref_name = $line["pref_name"];
-                       $value = $line["value"];
-                       $def_value = $line["def_value"];
-                       $help_text = $line["help_text"];
-
-                       print "<td width=\"40%\" class=\"prefName\" id=\"$pref_name\">" . __($line["short_desc"]);
-
-                       if ($help_text) print "<div class=\"prefHelp\">".__($help_text)."</div>";
-
-                       print "</td>";
-
-                       print "<td class=\"prefValue\">";
-
-                       if ($pref_name == "USER_TIMEZONE") {
-
-                               $timezones = explode("\n", file_get_contents("lib/timezones.txt"));
-
-                               print_select($pref_name, $value, $timezones, 'dojoType="dijit.form.FilteringSelect"');
-                       } else if ($pref_name == "USER_STYLESHEET") {
-
-                               print "<button dojoType=\"dijit.form.Button\"
-                                       onclick=\"customizeCSS()\">" . __('Customize') . "</button>";
-
-                       } else if ($pref_name == "DEFAULT_ARTICLE_LIMIT") {
-
-                               $limits = array(15, 30, 45, 60);
-
-                               print_select($pref_name, $value, $limits,
-                                       'dojoType="dijit.form.Select"');
-
-                       } else if ($pref_name == "DEFAULT_UPDATE_INTERVAL") {
-
-                               global $update_intervals_nodefault;
-
-                               print_select_hash($pref_name, $value, $update_intervals_nodefault,
-                                       'dojoType="dijit.form.Select"');
-
-                       } else if ($type_name == "bool") {
-
-                               if ($value == "true") {
-                                       $value = __("Yes");
-                               } else {
-                                       $value = __("No");
-                               }
-
-                               if ($pref_name == "PURGE_UNREAD_ARTICLES" && FORCE_ARTICLE_PURGE != 0) {
-                                       $disabled = "disabled=\"1\"";
-                                       $value = __("Yes");
-                               } else {
-                                       $disabled = "";
-                               }
-
-                               print_radio($pref_name, $value, __("Yes"), array(__("Yes"), __("No")),
-                                       $disabled);
-
-                       } else if (array_search($pref_name, array('FRESH_ARTICLE_MAX_AGE', 'DEFAULT_ARTICLE_LIMIT',
-                                       'PURGE_OLD_DAYS', 'LONG_DATE_FORMAT', 'SHORT_DATE_FORMAT')) !== false) {
-
-                               $regexp = ($type_name == 'integer') ? 'regexp="^\d*$"' : '';
-
-                               if ($pref_name == "PURGE_OLD_DAYS" && FORCE_ARTICLE_PURGE != 0) {
-                                       $disabled = "disabled=\"1\"";
-                                       $value = FORCE_ARTICLE_PURGE;
-                               } else {
-                                       $disabled = "";
-                               }
-
-                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
-                                       required=\"1\" $regexp $disabled
-                                       name=\"$pref_name\" value=\"$value\">";
-
-                       } else if ($pref_name == "SSL_CERT_SERIAL") {
-
-                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
-                                       id=\"SSL_CERT_SERIAL\" readonly=\"1\"
-                                       name=\"$pref_name\" value=\"$value\">";
-
-                               $cert_serial = htmlspecialchars(get_ssl_certificate_id());
-                               $has_serial = ($cert_serial) ? "false" : "true";
-
-                               print " <button dojoType=\"dijit.form.Button\" disabled=\"$has_serial\"
-                                       onclick=\"insertSSLserial('$cert_serial')\">" .
-                                       __('Register') . "</button>";
-
-                               print " <button dojoType=\"dijit.form.Button\"
-                                       onclick=\"insertSSLserial('')\">" .
-                                       __('Clear') . "</button>";
-
-                       } else if ($pref_name == 'DIGEST_PREFERRED_TIME') {
-                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
-                                       id=\"$pref_name\" regexp=\"[012]?\d:\d\d\" placeHolder=\"12:00\"
-                                       name=\"$pref_name\" value=\"$value\"><div class=\"insensitive\">".
-                                       T_sprintf("Current server time: %s (UTC)", date("H:i")) . "</div>";
-                       } else {
-                               $regexp = ($type_name == 'integer') ? 'regexp="^\d*$"' : '';
-
-                               print "<input dojoType=\"dijit.form.ValidationTextBox\"
-                                       $regexp
-                                       name=\"$pref_name\" value=\"$value\">";
-                       }
-
-                       print "</td>";
-
-                       print "</tr>";
-
-                       $lnum++;
-               }
-
-               print "</table>";
-
-               print '</div>'; # inside pane
-               print '<div dojoType="dijit.layout.ContentPane" region="bottom">';
-
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-prefs\">";
-               print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"saveconfig\">";
-
-               print "<button dojoType=\"dijit.form.Button\" type=\"submit\">".
-                       __('Save configuration')."</button> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return editProfiles()\">".
-                       __('Manage profiles')."</button> ";
-
-               print "<button dojoType=\"dijit.form.Button\" onclick=\"return validatePrefsReset()\">".
-                       __('Reset to defaults')."</button>";
-
-               print '</div>'; # inner pane
-               print '</div>'; # border container
-
-               print "</form>";
-
-               print "</div>"; #pane
-               print "</div>"; #container
-       }
-}
-?>
diff --git a/classes/pref_users.php b/classes/pref_users.php
deleted file mode 100644 (file)
index 8f8f819..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-<?php
-class Pref_Users extends Protected_Handler {
-               function before($method) {
-                       if (parent::before($method)) {
-                               if ($_SESSION["access_level"] < 10) {
-                                       print __("Your access level is insufficient to open this tab.");
-                                       return false;
-                               }
-                               return true;
-                       }
-                       return false;
-               }
-
-               function csrf_ignore($method) {
-                       $csrf_ignored = array("index");
-
-                       return array_search($method, $csrf_ignored) !== false;
-               }
-
-               function userdetails() {
-
-                       header("Content-Type: text/xml");
-                       print "<dlg>";
-
-                       $uid = sprintf("%d", $_REQUEST["id"]);
-
-                       print "<title>".__('User details')."</title>";
-
-                       print "<content><![CDATA[";
-
-                       $result = db_query($this->link, "SELECT login,
-                               ".SUBSTRING_FOR_DATE."(last_login,1,16) AS last_login,
-                               access_level,
-                               (SELECT COUNT(int_id) FROM ttrss_user_entries
-                                       WHERE owner_uid = id) AS stored_articles,
-                               ".SUBSTRING_FOR_DATE."(created,1,16) AS created
-                               FROM ttrss_users
-                               WHERE id = '$uid'");
-
-                       if (db_num_rows($result) == 0) {
-                               print "<h1>".__('User not found')."</h1>";
-                               return;
-                       }
-
-                       // print "<h1>User Details</h1>";
-
-                       $login = db_fetch_result($result, 0, "login");
-
-                       print "<table width='100%'>";
-
-                       $last_login = make_local_datetime($this->link,
-                               db_fetch_result($result, 0, "last_login"), true);
-
-                       $created = make_local_datetime($this->link,
-                               db_fetch_result($result, 0, "created"), true);
-
-                       $access_level = db_fetch_result($result, 0, "access_level");
-                       $stored_articles = db_fetch_result($result, 0, "stored_articles");
-
-                       print "<tr><td>".__('Registered')."</td><td>$created</td></tr>";
-                       print "<tr><td>".__('Last logged in')."</td><td>$last_login</td></tr>";
-
-                       $result = db_query($this->link, "SELECT COUNT(id) as num_feeds FROM ttrss_feeds
-                               WHERE owner_uid = '$uid'");
-
-                       $num_feeds = db_fetch_result($result, 0, "num_feeds");
-
-                       print "<tr><td>".__('Subscribed feeds count')."</td><td>$num_feeds</td></tr>";
-
-                       print "</table>";
-
-                       print "<h1>".__('Subscribed feeds')."</h1>";
-
-                       $result = db_query($this->link, "SELECT id,title,site_url FROM ttrss_feeds
-                               WHERE owner_uid = '$uid' ORDER BY title");
-
-                       print "<ul class=\"userFeedList\">";
-
-                       $row_class = "odd";
-
-                       while ($line = db_fetch_assoc($result)) {
-
-                               $icon_file = ICONS_URL."/".$line["id"].".ico";
-
-                               if (file_exists($icon_file) && filesize($icon_file) > 0) {
-                                       $feed_icon = "<img class=\"tinyFeedIcon\" src=\"$icon_file\">";
-                               } else {
-                                       $feed_icon = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\">";
-                               }
-
-                               print "<li class=\"$row_class\">$feed_icon&nbsp;<a href=\"".$line["site_url"]."\">".$line["title"]."</a></li>";
-
-                               $row_class = $row_class == "even" ? "odd" : "even";
-
-                       }
-
-                       if (db_num_rows($result) < $num_feeds) {
-                               // FIXME - add link to show ALL subscribed feeds here somewhere
-                               print "<li><img
-                                       class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\">&nbsp;...</li>";
-                       }
-
-                       print "</ul>";
-
-                       print "<div align='center'>
-                               <button onclick=\"closeInfoBox()\">".__("Close this window").
-                               "</button></div>";
-
-                       print "]]></content></dlg>";
-
-                       return;
-               }
-
-               function edit() {
-                       global $access_level_names;
-
-                       header("Content-Type: text/xml");
-
-                       $id = db_escape_string($_REQUEST["id"]);
-
-                       print "<dlg id=\"$method\">";
-                       print "<title>".__('User Editor')."</title>";
-                       print "<content><![CDATA[";
-
-                       print "<form id=\"user_edit_form\" onsubmit='return false'>";
-
-                       print "<input type=\"hidden\" name=\"id\" value=\"$id\">";
-                       print "<input type=\"hidden\" name=\"op\" value=\"pref-users\">";
-                       print "<input type=\"hidden\" name=\"method\" value=\"editSave\">";
-
-                       $result = db_query($this->link, "SELECT * FROM ttrss_users WHERE id = '$id'");
-
-                       $login = db_fetch_result($result, 0, "login");
-                       $access_level = db_fetch_result($result, 0, "access_level");
-                       $email = db_fetch_result($result, 0, "email");
-
-                       $sel_disabled = ($id == $_SESSION["uid"]) ? "disabled" : "";
-
-                       print "<div class=\"dlgSec\">".__("User")."</div>";
-                       print "<div class=\"dlgSecCont\">";
-
-                       if ($sel_disabled) {
-                               print "<input type=\"hidden\" name=\"login\" value=\"$login\">";
-                               print "<input size=\"30\" style=\"font-size : 16px\"
-                                       onkeypress=\"return filterCR(event, userEditSave)\" $sel_disabled
-                                       value=\"$login\">";
-                       } else {
-                               print "<input size=\"30\" style=\"font-size : 16px\"
-                                       onkeypress=\"return filterCR(event, userEditSave)\" $sel_disabled
-                                       name=\"login\" value=\"$login\">";
-                       }
-
-                       print "</div>";
-
-                       print "<div class=\"dlgSec\">".__("Authentication")."</div>";
-                       print "<div class=\"dlgSecCont\">";
-
-                       print __('Access level: ') . " ";
-
-                       if (!$sel_disabled) {
-                               print_select_hash("access_level", $access_level, $access_level_names,
-                                       $sel_disabled);
-                       } else {
-                               print_select_hash("", $access_level, $access_level_names,
-                                       $sel_disabled);
-                               print "<input type=\"hidden\" name=\"access_level\" value=\"$access_level\">";
-                       }
-
-                       print "<br/>";
-
-                       print __('Change password to') .
-                               " <input size=\"20\" onkeypress=\"return filterCR(event, userEditSave)\"
-                               name=\"password\">";
-
-                       print "</div>";
-
-                       print "<div class=\"dlgSec\">".__("Options")."</div>";
-                       print "<div class=\"dlgSecCont\">";
-
-                       print __('E-mail: ').
-                               " <input size=\"30\" name=\"email\" onkeypress=\"return filterCR(event, userEditSave)\"
-                               value=\"$email\">";
-
-                       print "</div>";
-
-                       print "</table>";
-
-                       print "</form>";
-
-                       print "<div class=\"dlgButtons\">
-                               <button onclick=\"return userEditSave()\">".
-                                       __('Save')."</button>
-                               <button onclick=\"return userEditCancel()\">".
-                                       __('Cancel')."</button></div>";
-
-                       print "]]></content></dlg>";
-
-                       return;
-               }
-
-               function editSave() {
-                       $login = db_escape_string(trim($_REQUEST["login"]));
-                       $uid = db_escape_string($_REQUEST["id"]);
-                       $access_level = (int) $_REQUEST["access_level"];
-                       $email = db_escape_string(trim($_REQUEST["email"]));
-                       $password = db_escape_string(trim($_REQUEST["password"]));
-
-                       if ($password) {
-                               $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
-                               $pwd_hash = encrypt_password($password, $salt, true);
-                               $pass_query_part = "pwd_hash = '$pwd_hash', salt = '$salt',";
-                       } else {
-                               $pass_query_part = "";
-                       }
-
-                       db_query($this->link, "UPDATE ttrss_users SET $pass_query_part login = '$login',
-                               access_level = '$access_level', email = '$email' WHERE id = '$uid'");
-
-               }
-
-               function remove() {
-                       $ids = split(",", db_escape_string($_REQUEST["ids"]));
-
-                       foreach ($ids as $id) {
-                               if ($id != $_SESSION["uid"] && $id != 1) {
-                                       db_query($this->link, "DELETE FROM ttrss_tags WHERE owner_uid = '$id'");
-                                       db_query($this->link, "DELETE FROM ttrss_feeds WHERE owner_uid = '$id'");
-                                       db_query($this->link, "DELETE FROM ttrss_users WHERE id = '$id'");
-                               }
-                       }
-               }
-
-               function add() {
-
-                       $login = db_escape_string(trim($_REQUEST["login"]));
-                       $tmp_user_pwd = make_password(8);
-                       $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
-                       $pwd_hash = encrypt_password($tmp_user_pwd, $salt, true);
-
-                       $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
-                               login = '$login'");
-
-                       if (db_num_rows($result) == 0) {
-
-                               db_query($this->link, "INSERT INTO ttrss_users
-                                       (login,pwd_hash,access_level,last_login,created, salt)
-                                       VALUES ('$login', '$pwd_hash', 0, null, NOW(), '$salt')");
-
-
-                               $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
-                                       login = '$login' AND pwd_hash = '$pwd_hash'");
-
-                               if (db_num_rows($result) == 1) {
-
-                                       $new_uid = db_fetch_result($result, 0, "id");
-
-                                       print format_notice(T_sprintf("Added user <b>%s</b> with password <b>%s</b>",
-                                               $login, $tmp_user_pwd));
-
-                                       initialize_user($this->link, $new_uid);
-
-                               } else {
-
-                                       print format_warning(T_sprintf("Could not create user <b>%s</b>", $login));
-
-                               }
-                       } else {
-                               print format_warning(T_sprintf("User <b>%s</b> already exists.", $login));
-                       }
-               }
-
-               function resetPass() {
-
-                       $uid = db_escape_string($_REQUEST["id"]);
-
-                       $result = db_query($this->link, "SELECT login,email
-                               FROM ttrss_users WHERE id = '$uid'");
-
-                       $login = db_fetch_result($result, 0, "login");
-                       $email = db_fetch_result($result, 0, "email");
-                       $salt = db_fetch_result($result, 0, "salt");
-
-                       $new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
-                       $tmp_user_pwd = make_password(8);
-
-                       $pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true);
-
-                       db_query($this->link, "UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt'
-                               WHERE id = '$uid'");
-
-                       print T_sprintf("Changed password of user <b>%s</b>
-                                to <b>%s</b>", $login, $tmp_user_pwd);
-
-                       require_once 'lib/phpmailer/class.phpmailer.php';
-
-                       if ($email) {
-                               print " ";
-                               print T_sprintf("Notifying <b>%s</b>.", $email);
-
-                               require_once "lib/MiniTemplator.class.php";
-
-                               $tpl = new MiniTemplator;
-
-                               $tpl->readTemplateFromFile("templates/resetpass_template.txt");
-
-                               $tpl->setVariable('LOGIN', $login);
-                               $tpl->setVariable('NEWPASS', $tmp_user_pwd);
-
-                               $tpl->addBlock('message');
-
-                               $message = "";
-
-                               $tpl->generateOutputToString($message);
-
-                               $mail = new PHPMailer();
-
-                               $mail->PluginDir = "lib/phpmailer/";
-                               $mail->SetLanguage("en", "lib/phpmailer/language/");
-
-                               $mail->CharSet = "UTF-8";
-
-                               $mail->From = SMTP_FROM_ADDRESS;
-                               $mail->FromName = SMTP_FROM_NAME;
-                               $mail->AddAddress($email, $login);
-
-                               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 = __("[tt-rss] Password change notification");
-                               $mail->Body = $message;
-
-                               $rc = $mail->Send();
-
-                               if (!$rc) print_error($mail->ErrorInfo);
-                       }
-
-                       print "</div>";
-               }
-
-               function index() {
-
-                       global $access_level_names;
-
-                       print "<div id=\"pref-user-wrap\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\">";
-                       print "<div id=\"pref-user-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
-
-                       print "<div id=\"pref-user-toolbar\" dojoType=\"dijit.Toolbar\">";
-
-                       $user_search = db_escape_string($_REQUEST["search"]);
-
-                       if (array_key_exists("search", $_REQUEST)) {
-                               $_SESSION["prefs_user_search"] = $user_search;
-                       } else {
-                               $user_search = $_SESSION["prefs_user_search"];
-                       }
-
-                       print "<div style='float : right; padding-right : 4px;'>
-                               <input dojoType=\"dijit.form.TextBox\" id=\"user_search\" size=\"20\" type=\"search\"
-                                       value=\"$user_search\">
-                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:updateUsersList()\">".
-                                       __('Search')."</button>
-                               </div>";
-
-                       $sort = db_escape_string($_REQUEST["sort"]);
-
-                       if (!$sort || $sort == "undefined") {
-                               $sort = "login";
-                       }
-
-                       print "<div dojoType=\"dijit.form.DropDownButton\">".
-                                       "<span>" . __('Select')."</span>";
-                       print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
-                       print "<div onclick=\"selectTableRows('prefUserList', 'all')\"
-                               dojoType=\"dijit.MenuItem\">".__('All')."</div>";
-                       print "<div onclick=\"selectTableRows('prefUserList', 'none')\"
-                               dojoType=\"dijit.MenuItem\">".__('None')."</div>";
-                       print "</div></div>";
-
-                       print "<button dojoType=\"dijit.form.Button\" onclick=\"javascript:addUser()\">".__('Create user')."</button>";
-
-                       print "
-                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:selectedUserDetails()\">".
-                               __('Details')."</button dojoType=\"dijit.form.Button\">
-                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:editSelectedUser()\">".
-                               __('Edit')."</button dojoType=\"dijit.form.Button\">
-                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:removeSelectedUsers()\">".
-                               __('Remove')."</button dojoType=\"dijit.form.Button\">
-                               <button dojoType=\"dijit.form.Button\" onclick=\"javascript:resetSelectedUserPass()\">".
-                               __('Reset password')."</button dojoType=\"dijit.form.Button\">";
-
-                       print "</div>"; #toolbar
-                       print "</div>"; #pane
-                       print "<div id=\"pref-user-content\" dojoType=\"dijit.layout.ContentPane\" region=\"center\">";
-
-                       print "<div id=\"sticky-status-msg\"></div>";
-
-                       if ($user_search) {
-
-                               $user_search = split(" ", $user_search);
-                               $tokens = array();
-
-                               foreach ($user_search as $token) {
-                                       $token = trim($token);
-                                       array_push($tokens, "(UPPER(login) LIKE UPPER('%$token%'))");
-                               }
-
-                               $user_search_query = "(" . join($tokens, " AND ") . ") AND ";
-
-                       } else {
-                               $user_search_query = "";
-                       }
-
-                       $result = db_query($this->link, "SELECT
-                                       id,login,access_level,email,
-                                       ".SUBSTRING_FOR_DATE."(last_login,1,16) as last_login,
-                                       ".SUBSTRING_FOR_DATE."(created,1,16) as created
-                               FROM
-                                       ttrss_users
-                               WHERE
-                                       $user_search_query
-                                       id > 0
-                               ORDER BY $sort");
-
-                       if (db_num_rows($result) > 0) {
-
-                       print "<p><table width=\"100%\" cellspacing=\"0\"
-                               class=\"prefUserList\" id=\"prefUserList\">";
-
-                       print "<tr class=\"title\">
-                                               <td align='center' width=\"5%\">&nbsp;</td>
-                                               <td width=''><a href=\"#\" onclick=\"updateUsersList('login')\">".__('Login')."</a></td>
-                                               <td width='20%'><a href=\"#\" onclick=\"updateUsersList('access_level')\">".__('Access Level')."</a></td>
-                                               <td width='20%'><a href=\"#\" onclick=\"updateUsersList('created')\">".__('Registered')."</a></td>
-                                               <td width='20%'><a href=\"#\" onclick=\"updateUsersList('last_login')\">".__('Last login')."</a></td></tr>";
-
-                       $lnum = 0;
-
-                       while ($line = db_fetch_assoc($result)) {
-
-                               $class = ($lnum % 2) ? "even" : "odd";
-
-                               $uid = $line["id"];
-
-                               print "<tr class=\"$class\" id=\"UMRR-$uid\">";
-
-                               $line["login"] = htmlspecialchars($line["login"]);
-
-                               $line["created"] = make_local_datetime($this->link, $line["created"], false);
-                               $line["last_login"] = make_local_datetime($this->link, $line["last_login"], false);
-
-                               print "<td align='center'><input onclick='toggleSelectRow(this);'
-                                       type=\"checkbox\" id=\"UMCHK-$uid\"></td>";
-
-                               $onclick = "onclick='editUser($uid, event)' title='".__('Click to edit')."'";
-
-                               print "<td $onclick>" . $line["login"] . "</td>";
-
-                               if (!$line["email"]) $line["email"] = "&nbsp;";
-
-                               print "<td $onclick>" . $access_level_names[$line["access_level"]] . "</td>";
-                               print "<td $onclick>" . $line["created"] . "</td>";
-                               print "<td $onclick>" . $line["last_login"] . "</td>";
-
-                               print "</tr>";
-
-                               ++$lnum;
-                       }
-
-                       print "</table>";
-
-                       } else {
-                               print "<p>";
-                               if (!$user_search) {
-                                       print_warning(__('No users defined.'));
-                               } else {
-                                       print_warning(__('No matching users found.'));
-                               }
-                               print "</p>";
-
-                       }
-
-                       print "</div>"; #pane
-                       print "</div>"; #container
-
-               }
-
-       }
-?>
diff --git a/classes/protected_handler.php b/classes/protected_handler.php
deleted file mode 100644 (file)
index 5d8d690..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-class Protected_Handler extends Handler {
-
-       function before($method) {
-               return parent::before($method) && $_SESSION['uid'];
-       }
-}
-?>
diff --git a/classes/public_handler.php b/classes/public_handler.php
deleted file mode 100644 (file)
index 5b7b523..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-<?php
-class Public_Handler extends Handler {
-
-       private function generate_syndicated_feed($owner_uid, $feed, $is_cat,
-               $limit, $search, $search_mode, $match_on, $view_mode = false) {
-
-               require_once "lib/MiniTemplator.class.php";
-
-               $note_style =   "background-color : #fff7d5;
-                       border-width : 1px; ".
-                       "padding : 5px; border-style : dashed; border-color : #e7d796;".
-                       "margin-bottom : 1em; color : #9a8c59;";
-
-               if (!$limit) $limit = 30;
-
-               if (get_pref($this->link, "SORT_HEADLINES_BY_FEED_DATE", $owner_uid)) {
-                       $date_sort_field = "updated";
-               } else {
-                       $date_sort_field = "date_entered";
-               }
-
-               $qfh_ret = queryFeedHeadlines($this->link, $feed,
-                       $limit, $view_mode, $is_cat, $search, $search_mode,
-                       $match_on, "$date_sort_field DESC", 0, $owner_uid);
-
-               $result = $qfh_ret[0];
-               $feed_title = htmlspecialchars($qfh_ret[1]);
-               $feed_site_url = $qfh_ret[2];
-               $last_error = $qfh_ret[3];
-
-               $feed_self_url = get_self_url_prefix() .
-                       "/public.php?op=rss&id=-2&key=" .
-                       get_feed_access_key($this->link, -2, false, $owner_uid);
-
-               if (!$feed_site_url) $feed_site_url = get_self_url_prefix();
-
-               $tpl = new MiniTemplator;
-
-               $tpl->readTemplateFromFile("templates/generated_feed.txt");
-
-               $tpl->setVariable('FEED_TITLE', $feed_title, true);
-               $tpl->setVariable('VERSION', VERSION, true);
-               $tpl->setVariable('FEED_URL', htmlspecialchars($feed_self_url), true);
-
-               if (PUBSUBHUBBUB_HUB && $feed == -2) {
-                       $tpl->setVariable('HUB_URL', htmlspecialchars(PUBSUBHUBBUB_HUB), true);
-                       $tpl->addBlock('feed_hub');
-               }
-
-               $tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
-
-               while ($line = db_fetch_assoc($result)) {
-                       $tpl->setVariable('ARTICLE_ID', htmlspecialchars($line['link']), true);
-                       $tpl->setVariable('ARTICLE_LINK', htmlspecialchars($line['link']), true);
-                       $tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
-                       $tpl->setVariable('ARTICLE_EXCERPT',
-                               truncate_string(strip_tags($line["content_preview"]), 100, '...'), true);
-
-                       $content = sanitize($this->link, $line["content_preview"], false, $owner_uid);
-
-                       if ($line['note']) {
-                               $content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
-                                       $content;
-                       }
-
-                       $tpl->setVariable('ARTICLE_CONTENT', $content, true);
-
-                       $tpl->setVariable('ARTICLE_UPDATED_ATOM',
-                               date('c', strtotime($line["updated"])), true);
-                       $tpl->setVariable('ARTICLE_UPDATED_RFC822',
-                               date(DATE_RFC822, strtotime($line["updated"])), true);
-
-                       $tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
-
-                       $tags = get_article_tags($this->link, $line["id"], $owner_uid);
-
-                       foreach ($tags as $tag) {
-                               $tpl->setVariable('ARTICLE_CATEGORY', htmlspecialchars($tag), true);
-                               $tpl->addBlock('category');
-                       }
-
-                       $enclosures = get_article_enclosures($this->link, $line["id"]);
-
-                       foreach ($enclosures as $e) {
-                               $type = htmlspecialchars($e['content_type']);
-                               $url = htmlspecialchars($e['content_url']);
-                               $length = $e['duration'];
-
-                               $tpl->setVariable('ARTICLE_ENCLOSURE_URL', $url, true);
-                               $tpl->setVariable('ARTICLE_ENCLOSURE_TYPE', $type, true);
-                               $tpl->setVariable('ARTICLE_ENCLOSURE_LENGTH', $length, true);
-
-                               $tpl->addBlock('enclosure');
-                       }
-
-                       $tpl->addBlock('entry');
-               }
-
-               $tmp = "";
-
-               $tpl->addBlock('feed');
-               $tpl->generateOutputToString($tmp);
-
-               print $tmp;
-       }
-
-       function getUnread() {
-               $login = db_escape_string($_REQUEST["login"]);
-               $fresh = $_REQUEST["fresh"] == "1";
-
-               $result = db_query($this->link, "SELECT id FROM ttrss_users WHERE login = '$login'");
-
-               if (db_num_rows($result) == 1) {
-                       $uid = db_fetch_result($result, 0, "id");
-
-                       print getGlobalUnread($this->link, $uid);
-
-                       if ($fresh) {
-                               print ";";
-                               print getFeedArticles($this->link, -3, false, true, $uid);
-                       }
-
-               } else {
-                       print "-1;User not found";
-               }
-
-       }
-
-       function getProfiles() {
-               $login = db_escape_string($_REQUEST["login"]);
-               $password = db_escape_string($_REQUEST["password"]);
-
-               if (authenticate_user($this->link, $login, $password)) {
-                       $result = db_query($this->link, "SELECT * FROM ttrss_settings_profiles
-                               WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY title");
-
-                       print "<select style='width: 100%' name='profile'>";
-
-                       print "<option value='0'>" . __("Default profile") . "</option>";
-
-                       while ($line = db_fetch_assoc($result)) {
-                               $id = $line["id"];
-                               $title = $line["title"];
-
-                               print "<option value='$id'>$title</option>";
-                       }
-
-                       print "</select>";
-
-                       $_SESSION = array();
-               }
-       }
-
-       function pubsub() {
-               $mode = db_escape_string($_REQUEST['hub_mode']);
-               $feed_id = (int) db_escape_string($_REQUEST['id']);
-               $feed_url = db_escape_string($_REQUEST['hub_topic']);
-
-               if (!PUBSUBHUBBUB_ENABLED) {
-                       header('HTTP/1.0 404 Not Found');
-                       echo "404 Not found";
-                       return;
-               }
-
-               // TODO: implement hub_verifytoken checking
-
-               $result = db_query($this->link, "SELECT feed_url FROM ttrss_feeds
-                       WHERE id = '$feed_id'");
-
-               if (db_num_rows($result) != 0) {
-
-                       $check_feed_url = db_fetch_result($result, 0, "feed_url");
-
-                       if ($check_feed_url && ($check_feed_url == $feed_url || !$feed_url)) {
-                               if ($mode == "subscribe") {
-
-                                       db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 2
-                                               WHERE id = '$feed_id'");
-
-                                       print $_REQUEST['hub_challenge'];
-                                       return;
-
-                               } else if ($mode == "unsubscribe") {
-
-                                       db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0
-                                               WHERE id = '$feed_id'");
-
-                                       print $_REQUEST['hub_challenge'];
-                                       return;
-
-                               } else if (!$mode) {
-
-                                       // Received update ping, schedule feed update.
-                                       //update_rss_feed($this->link, $feed_id, true, true);
-
-                                       db_query($this->link, "UPDATE ttrss_feeds SET
-                                               last_update_started = '1970-01-01',
-                                               last_updated = '1970-01-01' WHERE id = '$feed_id'");
-
-                               }
-                       } else {
-                               header('HTTP/1.0 404 Not Found');
-                               echo "404 Not found";
-                       }
-               } else {
-                       header('HTTP/1.0 404 Not Found');
-                       echo "404 Not found";
-               }
-
-       }
-
-       function logout() {
-               logout_user();
-               header("Location: index.php");
-       }
-
-       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)));
-               }
-       }
-
-       function share() {
-               $uuid = db_escape_string($_REQUEST["key"]);
-
-               $result = db_query($this->link, "SELECT ref_id, owner_uid FROM ttrss_user_entries WHERE
-                       uuid = '$uuid'");
-
-               if (db_num_rows($result) != 0) {
-                       header("Content-Type: text/html");
-
-                       $id = db_fetch_result($result, 0, "ref_id");
-                       $owner_uid = db_fetch_result($result, 0, "owner_uid");
-
-                       $article = format_article($this->link, $id, false, true, $owner_uid);
-
-                       print_r($article['content']);
-
-               } else {
-                       print "Article not found.";
-               }
-
-       }
-
-       function rss() {
-               header("Content-Type: text/xml; charset=utf-8");
-
-               $feed = db_escape_string($_REQUEST["id"]);
-               $key = db_escape_string($_REQUEST["key"]);
-               $is_cat = $_REQUEST["is_cat"] != false;
-               $limit = (int)db_escape_string($_REQUEST["limit"]);
-
-               $search = db_escape_string($_REQUEST["q"]);
-               $match_on = db_escape_string($_REQUEST["m"]);
-               $search_mode = db_escape_string($_REQUEST["smode"]);
-               $view_mode = db_escape_string($_REQUEST["view-mode"]);
-
-               if (SINGLE_USER_MODE) {
-                       authenticate_user($this->link, "admin", null);
-               }
-
-               $owner_id = false;
-
-               if ($key) {
-                       $result = db_query($this->link, "SELECT owner_uid FROM
-                               ttrss_access_keys WHERE access_key = '$key' AND feed_id = '$feed'");
-
-                       if (db_num_rows($result) == 1)
-                               $owner_id = db_fetch_result($result, 0, "owner_uid");
-               }
-
-               if ($owner_id) {
-                       $this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
-                               $search, $search_mode, $match_on, $view_mode);
-               } else {
-                       header('HTTP/1.1 403 Forbidden');
-               }
-       }
-
-       function globalUpdateFeeds() {
-               include "rssfuncs.php";
-               // Update all feeds needing a update.
-               update_daemon_common($this->link, 0, true, false);
-       }
-}
-?>
index bf693d2a2049bc3d61fe68a1c14401213f88c374..d9caae4db282c363a42f60eed86504f35ba43e91 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-class RPC extends Protected_Handler {
+class RPC extends Handler_Protected {
 
        function csrf_ignore($method) {
                $csrf_ignored = array("sanitycheck", "buttonplugin", "exportget");
@@ -766,7 +766,7 @@ class RPC extends Protected_Handler {
        }
 
        function buttonPlugin() {
-               $pclass = basename($_REQUEST['plugin']) . "_button";
+               $pclass = "button_" . basename($_REQUEST['plugin']);
                $method = $_REQUEST['plugin_method'];
 
                if (class_exists($pclass)) {
diff --git a/classes/share_button.php b/classes/share_button.php
deleted file mode 100644 (file)
index 9402edd..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-class Share_Button extends Plugin_Button {
-       function render($article_id, $line) {
-               return "<img src=\"".theme_image($this->link, 'images/art-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>";
-       }
-
-
-}
-?>
diff --git a/classes/tweet_button.php b/classes/tweet_button.php
deleted file mode 100644 (file)
index 470bc63..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-class Tweet_Button extends Plugin_Button {
-       function render($article_id) {
-               $rv = "<img src=\"".theme_image($this->link, 'images/art-tweet.png')."\"
-                       class='tagsPic' style=\"cursor : pointer\"
-                       onclick=\"tweetArticle($article_id)\"
-                       title='".__('Share on Twitter')."'>";
-
-               return $rv;
-       }
-
-       function getTweetInfo() {
-               $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));
-       }
-
-
-}
-?>
index 702843c1601416d6b303447a99b1226de89e3eca..ac07974e8b70d435f64028220263e57848a385cb 100644 (file)
@@ -3,7 +3,10 @@
        define('SCHEMA_VERSION', 94);
 
        function __autoload($class) {
-               $file = dirname(__FILE__)."/../classes/".strtolower(basename($class)).".php";
+               $class_file = str_replace("_", "/", strtolower(basename($class)));
+
+               $file = dirname(__FILE__)."/../classes/$class_file.php";
+
                if (file_exists($file)) {
                        require $file;
                }
        }
 
        function format_article($link, $id, $mark_as_read = true, $zoom_mode = false, $owner_uid = false) {
+               global $plugins;
 
                if (!$owner_uid) $owner_uid = $_SESSION["uid"];
 
 
                        $line = db_fetch_assoc($result);
 
+                       $plugins->hook('article_before', $line);
+
                        if ($line["icon_url"]) {
                                $feed_icon = "<img src=\"" . $line["icon_url"] . "\">";
                        } else {
                                $button_plugins = explode(",", ARTICLE_BUTTON_PLUGINS);
 
                                foreach ($button_plugins as $p) {
-                                       $pclass = trim("${p}_button");
+                                       $pclass = trim("button_${p}");
 
                                        if (class_exists($pclass)) {
                                                $plugin = new $pclass($link);
                        $rv['content'] .= "</body></html>";
                }
 
+               $plugins->hook('article_after', $rv);
+
                return $rv;
 
        }
index 59fa3d54781776d70d05d4ff6758b1455940195d..4ad08df32e7be7713d0bb45b3fff01e9be136004 100644 (file)
        function update_rss_feed($link, $feed, $ignore_daemon = false, $no_cache = false,
                $override_url = false) {
 
+               global $plugins;
+
                require_once "lib/simplepie/simplepie.inc";
                require_once "lib/magpierss/rss_fetch.inc";
                require_once 'lib/magpierss/rss_utils.inc';
                        }
 
                        foreach ($iterator as $item) {
+                               $hook_params = array("item" => &$item, "feed" => $feed);
+
+                               $plugins->hook('rss_update_item', $hook_params);
 
                                if ($_REQUEST['xdebug'] == 2) {
                                        print_r($item);
index a17fa5959fa24c68d2e14b7bb248c65b11de24ec..bf13fdd583040aa21f82c4226effe4458822b158 100644 (file)
@@ -40,7 +40,7 @@
 
        $method = $_REQUEST["op"];
 
-       $handler = new Public_Handler($link, $_REQUEST);
+       $handler = new Handler_Public($link, $_REQUEST);
 
        if ($handler->before($method)) {
                if ($method && method_exists($handler, $method)) {
index 292b5c1be12a9c2b52961fce00b3ca80d8d4948b..2c7f347d91ce86f41674956e926d7a1c3effe5fb 100755 (executable)
@@ -56,6 +56,8 @@
 
        init_connection($link);
 
+       $plugins = new Plugins($link);
+
        if (in_array("-feeds", $op)) {
                // Update all feeds needing a update.
                update_daemon_common($link);
index 6410709adf37882be1df4a7dc51bc663f4c13bd4..b79a1a2b282e32b6a015051063a702b83c990230 100755 (executable)
 
                                        if (!init_connection($link)) return;
 
+                                       $plugins = new Plugins($link);
+
                                        // We disable stamp file, since it is of no use in a multiprocess update.
                                        // not really, tho for the time being -fox
                                        if (!make_stampfile('update_daemon.stamp')) {