diff --git a/classes/pluginhost.php b/classes/pluginhost.php
index d97dfa66660a4f36568885d1295088e179b1d58d..d7db7481cc0cd31ec281be8271a42fcd3d7a731b 100644
--- a/classes/pluginhost.php
+++ b/classes/pluginhost.php
@@ -5,6 +5,8 @@ class PluginHost {
 	private $plugins = array();
 	private $handlers = array();
 	private $commands = array();
+	private $storage = array();
+	private $owner_uid;
 
 	const HOOK_ARTICLE_BUTTON = 1;
 	const HOOK_ARTICLE_FILTER = 2;
@@ -21,6 +23,10 @@ class PluginHost {
 
 	function __construct($link) {
 		$this->link = $link;
+
+		$this->storage = $_SESSION["plugin_storage"];
+
+		if (!$this->storage) $this->storage = array();
 	}
 
 	private function register_plugin($name, $plugin) {
@@ -70,14 +76,16 @@ class PluginHost {
 			return array();
 		}
 	}
-	function load_all($kind) {
+	function load_all($kind, $owner_uid = false) {
 		$plugins = array_map("basename", glob("plugins/*"));
-		$this->load(join(",", $plugins), $kind);
+		$this->load(join(",", $plugins), $kind, $owner_uid);
 	}
 
-	function load($classlist, $kind) {
+	function load($classlist, $kind, $owner_uid = false) {
 		$plugins = explode(",", $classlist);
 
+		$this->owner_uid = (int) $owner_uid;
+
 		foreach ($plugins as $class) {
 			$class = trim($class);
 			$class_file = strtolower(basename($class));
@@ -194,5 +202,89 @@ class PluginHost {
 		}
 	}
 
+	function load_data($force = false) {
+		if ($this->owner_uid && (!$_SESSION["plugin_storage"] || $force))  {
+			$plugin = db_escape_string($plugin);
+
+			$result = db_query($this->link, "SELECT name, content FROM ttrss_plugin_storage
+				WHERE owner_uid = '".$this->owner_uid."'");
+
+			while ($line = db_fetch_assoc($result)) {
+				$this->storage[$line["name"]] = unserialize($line["content"]);
+			}
+
+			$_SESSION["plugin_storage"] = $this->storage;
+		}
+	}
+
+	private function save_data($plugin) {
+		if ($this->owner_uid) {
+			$plugin = db_escape_string($plugin);
+
+			db_query($this->link, "BEGIN");
+
+			$result = db_query($this->link,"SELECT id FROM ttrss_plugin_storage WHERE
+				owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
+
+			if (!isset($this->storage[$plugin]))
+				$this->storage[$plugin] = array();
+
+			$content = db_escape_string(serialize($this->storage[$plugin]));
+
+			if (db_num_rows($result) != 0) {
+				db_query($this->link, "UPDATE ttrss_plugin_storage SET content = '$content'
+					WHERE owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
+
+			} else {
+				db_query($this->link, "INSERT INTO ttrss_plugin_storage
+					(name,owner_uid,content) VALUES
+					('$plugin','".$this->owner_uid."','$content')");
+			}
+
+			db_query($this->link, "COMMIT");
+		}
+	}
+
+	function set($sender, $name, $value, $sync = true) {
+		$idx = get_class($sender);
+
+		if (!isset($this->storage[$idx]))
+			$this->storage[$idx] = array();
+
+		$this->storage[$idx][$name] = $value;
+
+		$_SESSION["plugin_storage"] = $this->storage;
+
+		if ($sync) $this->save_data(get_class($sender));
+	}
+
+	function get($sender, $name, $default_value = false) {
+		$idx = get_class($sender);
+
+		if (isset($this->storage[$idx][$name])) {
+			return $this->storage[$idx][$name];
+		} else {
+			return $default_value;
+		}
+	}
+
+	function get_all($sender) {
+		$idx = get_class($sender);
+
+		return $this->storage[$idx];
+	}
+
+	function clear_data($sender) {
+		if ($this->owner_uid) {
+			$idx = get_class($sender);
+
+			unset($this->storage[$idx]);
+
+			db_query($this->link, "DELETE FROM ttrss_plugin_storage WHERE name = '$idx'
+				AND owner_uid = " . $this->owner_uid);
+
+			$_SESSION["plugin_storage"] = $this->storage;
+		}
+	}
 }
 ?>
diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php
index b423eab9525e6fb4aaa3cb9f13aa98ba7f6e0e27..452236a7edf3cba34c1a2a705d9b02a9025d55a8 100644
--- a/classes/pref/feeds.php
+++ b/classes/pref/feeds.php
@@ -949,7 +949,7 @@ class Pref_Feeds extends Handler_Protected {
 				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_on_checksum_change = $update_on_checksum_change
 			WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
 
 		} else {
diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php
index 0922e43a8068fcaa86bc6894699684e67ee28453..bb82b355edac60376e5539cbed5d8d9273939ecb 100644
--- a/classes/pref/prefs.php
+++ b/classes/pref/prefs.php
@@ -683,8 +683,9 @@ class Pref_Prefs extends Handler_Protected {
 		$system_enabled = array_map("trim", explode(",", PLUGINS));
 		$user_enabled = array_map("trim", explode(",", get_pref($this->link, "_ENABLED_PLUGINS")));
 
-		$tmppluginhost = new PluginHost($link);
-		$tmppluginhost->load_all($tmppluginhost::KIND_ALL);
+		$tmppluginhost = new PluginHost($this->link);
+		$tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"]);
+		$tmppluginhost->load_data(true);
 
 		foreach ($tmppluginhost->get_plugins() as $name => $plugin) {
 			$about = $plugin->about();
@@ -707,6 +708,11 @@ class Pref_Prefs extends Handler_Protected {
 				print "<td>" . htmlspecialchars(sprintf("%.2f", $about[0])) . "</td>";
 				print "<td>" . htmlspecialchars($about[2]) . "</td>";
 
+				if (count($tmppluginhost->get_all($plugin)) > 0) {
+					print "<td><a href='#' onclick=\"clearPluginData('$name')\"
+						class='visibleLink'>".__("Clear data")."</a></td>";
+				}
+
 				print "</tr>";
 
 			}
@@ -752,6 +758,10 @@ class Pref_Prefs extends Handler_Protected {
 				print "<td>" . htmlspecialchars(sprintf("%.2f", $about[0])) . "</td>";
 				print "<td>" . htmlspecialchars($about[2]) . "</td>";
 
+				if (count($tmppluginhost->get_all($plugin)) > 0) {
+					print "<td><a href='#' onclick=\"clearPluginData('$name')\" class='visibleLink'>".__("Clear data")."</a></td>";
+				}
+
 				print "</tr>";
 
 
@@ -846,5 +856,12 @@ class Pref_Prefs extends Handler_Protected {
 
 		set_pref($this->link, "_ENABLED_PLUGINS", $plugins);
 	}
+
+	function clearplugindata() {
+		$name = db_escape_string($_REQUEST["name"]);
+
+		global $pluginhost;
+		$pluginhost->clear_data($pluginhost->get_plugin($name));
+	}
 }
 ?>
diff --git a/include/functions.php b/include/functions.php
index f6ef7c2b370ca02ac9cf302f9824d968c36d305c..f0bd31831ab22d76ec18f3b16c133adf0beda350 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -1,6 +1,6 @@
 <?php
 	define('EXPECTED_CONFIG_VERSION', 26);
-	define('SCHEMA_VERSION', 100);
+	define('SCHEMA_VERSION', 101);
 
 	$fetch_last_error = false;
 	$pluginhost = false;
@@ -547,25 +547,6 @@
 		if (!SINGLE_USER_MODE) {
 
 			$user_id = false;
-			/* $modules = explode(",", AUTH_MODULES);
-
-			foreach ($modules as $module) {
-				$module_class = "auth_$module";
-				if (class_exists($module_class)) {
-					$authenticator = new $module_class($link);
-
-					$user_id = (int) $authenticator->authenticate($login, $password);
-
-					if ($user_id) {
-						$_SESSION["auth_module"] = $module;
-						break;
-					}
-
-				} else {
-					print T_sprintf("Fatal: authentication module %s not found.", $module);
-					die;
-				}
-			} */
 
 			global $pluginhost;
 			foreach ($pluginhost->get_hooks($pluginhost::HOOK_AUTH_USER) as $plugin) {
@@ -727,7 +708,11 @@
 			$plugins = get_pref($link, "_ENABLED_PLUGINS", $owner_uid);
 
 			global $pluginhost;
-			$pluginhost->load($plugins, $pluginhost::KIND_USER);
+			$pluginhost->load($plugins, $pluginhost::KIND_USER, $owner_uid);
+
+			if (get_schema_version($link) > 100) {
+				$pluginhost->load_data();
+			}
 		}
 	}
 
@@ -2590,7 +2575,8 @@
 
 		$node = $doc->getElementsByTagName('body')->item(0);
 
-		return $doc->saveXML($node); //LIBXML_NOEMPTYTAG
+		// http://tt-rss.org/redmine/issues/357
+		return $doc->saveXML($node, LIBXML_NOEMPTYTAG);
 	}
 
 	function check_for_update($link) {
@@ -4690,17 +4676,6 @@
 
 	}
 
-/*	function rewrite_urls($line) {
-		global $url_regex;
-
-		$urls = null;
-
-		$result = preg_replace("/((?<!=.)((http|https|ftp)+):\/\/[^ ,!]+)/i",
-			"<a target=\"_blank\" href=\"\\1\">\\1</a>", $line);
-
-		return $result;
-	} */
-
 	function rewrite_urls($html) {
 		libxml_use_internal_errors(true);
 
diff --git a/include/sanity_check.php b/include/sanity_check.php
index ee3a0b006540f6d707b76e2e97137036e6e3ae97..2a39cfa42fcf28e5727f6d0db2b8fc83ce8450b1 100644
--- a/include/sanity_check.php
+++ b/include/sanity_check.php
@@ -12,6 +12,10 @@
 
 			require_once "sanity_config.php";
 
+			if (strpos(PLUGINS, "auth_") === FALSE) {
+				array_push($errors, "Please enable at least one authentication module via PLUGINS constant in config.php");
+			}
+
 			if (function_exists('posix_getuid') && posix_getuid() == 0) {
 				array_push($errors, "Please don't run this script as root.");
 			}
diff --git a/js/prefs.js b/js/prefs.js
index 0b3f47c0aacfde212fbd7afbcff67bd897c5b955..7ee88ab56a137b11e535c5ccad2ebfd03ea7b2ce 100644
--- a/js/prefs.js
+++ b/js/prefs.js
@@ -1925,3 +1925,20 @@ function toggleAdvancedPrefs() {
 		exception_error("toggleAdvancedPrefs", e);
 	}
 }
+
+function clearPluginData(name) {
+	try {
+		if (confirm(__("Clear stored data for this plugin?"))) {
+			notify_progress("Loading, please wait...");
+
+			new Ajax.Request("backend.php", {
+				parameters: "?op=pref-prefs&method=clearplugindata&name=" + param_escape(name),
+				onComplete: function(transport) {
+					notify('');
+					updatePrefsList();
+				} });
+		}
+	} catch (e) {
+		exception_error("clearPluginData", e);
+	}
+}
diff --git a/plugins/example/example.php b/plugins/example/example.php
index eef604b4f599631a3e057a3d9e62be02c642fecc..f3788ae8c6fafec02be2f208d8751f5b349457f0 100644
--- a/plugins/example/example.php
+++ b/plugins/example/example.php
@@ -23,7 +23,9 @@ class Example extends Plugin {
 	function save() {
 		$example_value = db_escape_string($_POST["example_value"]);
 
-		echo "Value set to $example_value (not really)";
+		$this->host->set($this, "example", $example_value);
+
+		echo "Value set to $example_value";
 	}
 
 	function get_prefs_js() {
@@ -35,6 +37,13 @@ class Example extends Plugin {
 
 		print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Example Pane")."\">";
 
+		print "<br/>";
+
+//		print_r($this->host->set($this, "example", rand(0,100)));
+//		print_r($this->host->get_all($this));
+
+		$value = $this->host->get($this, "example");
+
 		print "<form dojoType=\"dijit.form.Form\">";
 
 		print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
@@ -47,7 +56,7 @@ class Example extends Plugin {
 						notify_info(transport.responseText);
 					}
 				});
-				this.reset();
+				//this.reset();
 			}
 			</script>";
 
@@ -58,7 +67,7 @@ class Example extends Plugin {
 		print "<table width=\"100%\" class=\"prefPrefsList\">";
 
 			print "<tr><td width=\"40%\">".__("Sample value")."</td>";
-			print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"example_value\"></td></tr>";
+			print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"example_value\" value=\"$value\"></td></tr>";
 
 			print "</table>";
 
diff --git a/schema/ttrss_schema_mysql.sql b/schema/ttrss_schema_mysql.sql
index bb8bd1028a2fb46580d88f6d48b720a5dea7e244..d4531308f80c92f2f4bf6757a8f940e081742025 100644
--- a/schema/ttrss_schema_mysql.sql
+++ b/schema/ttrss_schema_mysql.sql
@@ -1,6 +1,7 @@
 SET NAMES utf8;
 SET CHARACTER SET utf8;
 
+drop table if exists ttrss_plugin_storage;
 drop table if exists ttrss_linked_feeds;
 drop table if exists ttrss_linked_instances;
 drop table if exists ttrss_access_keys;
@@ -308,7 +309,7 @@ create table ttrss_tags (id integer primary key auto_increment,
 
 create table ttrss_version (schema_version int not null) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
 
-insert into ttrss_version values (100);
+insert into ttrss_version values (101);
 
 create table ttrss_enclosures (id integer primary key auto_increment,
 	content_url text not null,
@@ -528,4 +529,12 @@ create table ttrss_linked_feeds (
 	subscribers integer not null,
  	foreign key (instance_id) references ttrss_linked_instances(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
 
+create table ttrss_plugin_storage (
+	id integer not null auto_increment primary key,
+	name varchar(100) not null,
+	owner_uid integer not null,
+	content longtext not null,
+  	foreign key (owner_uid) references ttrss_users(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
+
+
 commit;
diff --git a/schema/ttrss_schema_pgsql.sql b/schema/ttrss_schema_pgsql.sql
index 3c508bb3439f0fc5bd30cb6e94d943e081c91ae7..f52d4191d30fe30384cc65368daf0b156d7a5d62 100644
--- a/schema/ttrss_schema_pgsql.sql
+++ b/schema/ttrss_schema_pgsql.sql
@@ -1,3 +1,4 @@
+drop table if exists ttrss_plugin_storage;
 drop table if exists ttrss_linked_feeds;
 drop table if exists ttrss_linked_instances;
 drop table if exists ttrss_access_keys;
@@ -256,7 +257,7 @@ create index ttrss_tags_post_int_id_idx on ttrss_tags(post_int_id);
 
 create table ttrss_version (schema_version int not null);
 
-insert into ttrss_version values (100);
+insert into ttrss_version values (101);
 
 create table ttrss_enclosures (id serial not null primary key,
 	content_url text not null,
@@ -461,4 +462,10 @@ create table ttrss_linked_feeds (
 	instance_id integer not null references ttrss_linked_instances(id) ON DELETE CASCADE,
 	subscribers integer not null);
 
+create table ttrss_plugin_storage (
+	id serial not null primary key,
+	name varchar(100) not null,
+	owner_uid integer not null references ttrss_users(id) ON DELETE CASCADE,
+	content text not null);
+
 commit;
diff --git a/schema/versions/mysql/101.sql b/schema/versions/mysql/101.sql
new file mode 100644
index 0000000000000000000000000000000000000000..47ff265228b41e6e4085d6fc000204f3bd282355
--- /dev/null
+++ b/schema/versions/mysql/101.sql
@@ -0,0 +1,12 @@
+begin;
+
+create table ttrss_plugin_storage (
+	id integer not null auto_increment primary key,
+	name varchar(100) not null,
+	owner_uid integer not null,
+	content longtext not null,
+  	foreign key (owner_uid) references ttrss_users(id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=UTF8;
+
+update ttrss_version set schema_version = 101;
+
+commit;
diff --git a/schema/versions/pgsql/101.sql b/schema/versions/pgsql/101.sql
new file mode 100644
index 0000000000000000000000000000000000000000..5be859002beec0e6cc0655e8c53ed7ed6454df94
--- /dev/null
+++ b/schema/versions/pgsql/101.sql
@@ -0,0 +1,11 @@
+begin;
+
+create table ttrss_plugin_storage (
+	id serial not null primary key,
+	name varchar(100) not null,
+	owner_uid integer not null references ttrss_users(id) ON DELETE CASCADE,
+	content text not null);
+
+update ttrss_version set schema_version = 101;
+
+commit;