diff --git a/src/_h5ai/config.js b/src/_h5ai/config.js
index ad119a29..48a08f31 100644
--- a/src/_h5ai/config.js
+++ b/src/_h5ai/config.js
@@ -10,10 +10,9 @@ var H5AI_CONFIG = {
 	"options": {
 
 		/*
-		The absolute links to webroot and h5ai.
-		Do not change this unless you know what you are doing.
+		The absolute link to h5ai.
+		Must point to the "_h5ai" directory.
 		*/
-		"rootAbsHref": "/",
 		"h5aiAbsHref": "/_h5ai/",
 
 		/*
diff --git a/src/_h5ai/config.php b/src/_h5ai/config.php
index 8292961d..e7fcd80a 100644
--- a/src/_h5ai/config.php
+++ b/src/_h5ai/config.php
@@ -10,12 +10,6 @@ global $H5AI_CONFIG;
 
 $H5AI_CONFIG = array(
 
-	/*
-	 * This configuration assumes that h5ai is installed
-	 * in the webroot directory of the web server.
-	 */
-	"ROOT_ABS_PATH" => dirname(dirname(__FILE__)),
-
 	/*
 	 * Files/folders that should not be listed. Specified
 	 * by the complete filename or by a regular expression.
@@ -26,7 +20,7 @@ $H5AI_CONFIG = array(
 
 	/*
 	 * Folders that contain one of these files will be considered
-	 * as none h5ai folders.
+	 * not to be h5ai indexed folders.
 	 */
 	"INDEX_FILES" => array("index.html", "index.htm", "index.php")
 );
diff --git a/src/_h5ai/js/inc/core/mode.js b/src/_h5ai/js/inc/core/mode.js
new file mode 100644
index 00000000..db8435ef
--- /dev/null
+++ b/src/_h5ai/js/inc/core/mode.js
@@ -0,0 +1,12 @@
+
+modulejs.define('core/mode', [], function () {
+
+	var mode = {
+			// id: null,
+			// dataType: null,
+			// serverName: null,
+			// serverVersion: null
+		};
+
+	return mode;
+});
diff --git a/src/_h5ai/js/inc/core/parser.js b/src/_h5ai/js/inc/core/parser.js
index 9002ef30..6b06915e 100644
--- a/src/_h5ai/js/inc/core/parser.js
+++ b/src/_h5ai/js/inc/core/parser.js
@@ -9,14 +9,7 @@ modulejs.define('core/parser', ['$'], function ($) {
 	}
 
 	return {
-		id: 'none',
-		mode: null,
-		server: {
-			name: null,
-			version: null
-		},
-		parse: function () {
-			return [];
-		}
+		dataType: 'N/A',
+		parse: function () { return []; }
 	};
 });
diff --git a/src/_h5ai/js/inc/core/refresh.js b/src/_h5ai/js/inc/core/refresh.js
index 5e5ac7cf..a8271cee 100644
--- a/src/_h5ai/js/inc/core/refresh.js
+++ b/src/_h5ai/js/inc/core/refresh.js
@@ -1,5 +1,5 @@
 
-modulejs.define('core/refresh', ['_', 'core/ajax', 'model/entry'], function (_, ajax, Entry) {
+modulejs.define('core/refresh', ['_', 'core/mode', 'core/ajax', 'model/entry'], function (_, mode, ajax, Entry) {
 
 	var parseJson = function (entry, json) {
 
@@ -20,6 +20,10 @@ modulejs.define('core/refresh', ['_', 'core/ajax', 'model/entry'], function (_,
 
 		refresh = function () {
 
+			if (mode.id !== 'php') {
+				return;
+			}
+
 			var entry = Entry.get();
 			ajax.getEntries(entry.absHref, 1, function (json) {
 
diff --git a/src/_h5ai/js/inc/core/settings.js b/src/_h5ai/js/inc/core/settings.js
index 5111291e..257d4239 100644
--- a/src/_h5ai/js/inc/core/settings.js
+++ b/src/_h5ai/js/inc/core/settings.js
@@ -3,10 +3,13 @@ modulejs.define('core/settings', ['config', '_'], function (config, _) {
 
 	var defaults = {
 			rootAbsHref: '/',
-			h5aiAbsHref: '/_h5ai/',
-			server: 'unknown',
-			mode: 'unknown'
+			h5aiAbsHref: '/_h5ai/'
 		};
 
-	return _.extend({}, defaults, config.options);
+	var settings = _.extend({}, defaults, config.options);
+
+	settings.h5aiAbsHref = settings.h5aiAbsHref.replace(/\/*$/, '/');
+	settings.rootAbsHref = /^(.*\/)[^\/]+\/?$/.exec(settings.h5aiAbsHref)[1];
+
+	return settings;
 });
diff --git a/src/_h5ai/js/inc/ext/crumb.js b/src/_h5ai/js/inc/ext/crumb.js
index 859154b0..43956067 100644
--- a/src/_h5ai/js/inc/ext/crumb.js
+++ b/src/_h5ai/js/inc/ext/crumb.js
@@ -39,6 +39,11 @@ modulejs.define('ext/crumb', ['_', '$', 'core/settings', 'core/resource', 'core/
 				$a.find('img').attr('src', resource.image('home'));
 			}
 
+			if (entry.isRoot()) {
+				$html.addClass('root');
+				$a.find('img').attr('src', resource.image('home'));
+			}
+
 			if (entry.isCurrentFolder()) {
 				$html.addClass('current');
 			}
diff --git a/src/_h5ai/js/inc/ext/mode.js b/src/_h5ai/js/inc/ext/mode.js
index 6b2cd6c1..174eb2d3 100644
--- a/src/_h5ai/js/inc/ext/mode.js
+++ b/src/_h5ai/js/inc/ext/mode.js
@@ -1,5 +1,5 @@
 
-modulejs.define('ext/mode', ['_', '$', 'core/settings', 'core/parser'], function (_, $, allsettings, parser) {
+modulejs.define('ext/mode', ['_', '$', 'core/mode', 'core/settings'], function (_, $, mode, allsettings) {
 
 	var defaults = {
 			enabled: false,
@@ -16,14 +16,14 @@ modulejs.define('ext/mode', ['_', '$', 'core/settings', 'core/parser'], function
 
 			var info = '';
 
-			if (parser.mode) {
-				info += parser.mode;
+			if (mode.id) {
+				info += mode.id;
 			}
-			if (settings.display > 0 && parser.server.name) {
-				info += (info ? ' on ' : '') + parser.server.name;
+			if (settings.display > 0 && mode.serverName) {
+				info += (info ? ' on ' : '') + mode.serverName;
 			}
-			if (settings.display > 1 && parser.server.version) {
-				info += (info ? '-' : '') + parser.server.version;
+			if (settings.display > 1 && mode.serverVersion) {
+				info += (info ? '-' : '') + mode.serverVersion;
 			}
 
 			if (info) {
diff --git a/src/_h5ai/js/inc/ext/tree.js b/src/_h5ai/js/inc/ext/tree.js
index 0d01fcb0..062df7e8 100644
--- a/src/_h5ai/js/inc/ext/tree.js
+++ b/src/_h5ai/js/inc/ext/tree.js
@@ -61,6 +61,12 @@ modulejs.define('ext/tree', ['_', '$', 'core/settings', 'core/resource', 'core/e
 					$img.attr('src', resource.icon('folder-home'));
 				}
 
+				// is it the root?
+				if (entry.isRoot()) {
+					$html.addClass('root');
+					$img.attr('src', resource.icon('folder-home'));
+				}
+
 				// is it the current folder?
 				if (entry.isCurrentFolder()) {
 					$html.addClass('current');
diff --git a/src/_h5ai/js/inc/model/entry.js b/src/_h5ai/js/inc/model/entry.js
index 9df15e94..f3d799f3 100644
--- a/src/_h5ai/js/inc/model/entry.js
+++ b/src/_h5ai/js/inc/model/entry.js
@@ -1,5 +1,5 @@
 
-modulejs.define('model/entry', ['_', 'core/types', 'core/ajax', 'core/event'], function (_, types, ajax, event) {
+modulejs.define('model/entry', ['_', 'core/types', 'core/ajax', 'core/event', 'core/settings'], function (_, types, ajax, event, settings) {
 
 	var doc = document,
 		domain = doc.domain,
@@ -59,33 +59,36 @@ modulejs.define('model/entry', ['_', 'core/types', 'core/ajax', 'core/event'], f
 		reEndsWithSlash = /\/$/,
 
 
+		startsWith = function (sequence, part) {
+
+			return sequence.length >= part.length && sequence.slice(0, part.length) === part;
+		},
+
+
 		createLabel = function (sequence) {
 
-			if (sequence.length > 1 && reEndsWithSlash.test(sequence)) {
-				sequence = sequence.slice(0, -1);
-			}
+			sequence = sequence.replace(reEndsWithSlash, '');
 			try { sequence = decodeURIComponent(sequence); } catch (e) {}
 			return sequence;
 		},
 
 
-		reSplitPath = /^\/([^\/]+\/?)$/,
-		reSplitPath2 = /^(\/(?:.*\/)*?([^\/]+)\/)([^\/]+\/?)$/,
+		reSplitPath = /^(.*\/)([^\/]+\/?)$/,
 
 		splitPath = function (sequence) {
 
-			var match;
-
 			if (sequence === '/') {
 				return { parent: null, name: '/' };
 			}
-			match = reSplitPath2.exec(sequence);
+
+			var match = reSplitPath.exec(sequence);
 			if (match) {
-				return { parent: match[1], name: match[3] };
-			}
-			match = reSplitPath.exec(sequence);
-			if (match) {
-				return { parent: '/', name: match[1] };
+				var split = { parent: match[1], name: match[2] };
+
+				if (split.parent && !startsWith(split.parent, settings.rootAbsHref)) {
+					split.parent = null;
+				}
+				return split;
 			}
 		},
 
@@ -112,6 +115,10 @@ modulejs.define('model/entry', ['_', 'core/types', 'core/ajax', 'core/event'], f
 
 			absHref = forceEncoding(absHref || location);
 
+			if (!startsWith(absHref, settings.rootAbsHref)) {
+				return null;
+			}
+
 			var created = !cache[absHref],
 				changed = false;
 
@@ -251,6 +258,16 @@ modulejs.define('model/entry', ['_', 'core/types', 'core/ajax', 'core/event'], f
 			return this.absHref === '/';
 		},
 
+		isRoot: function () {
+
+			return this.absHref === settings.rootAbsHref;
+		},
+
+		isH5ai: function () {
+
+			return this.absHref === settings.h5aiAbsHref;
+		},
+
 		isEmpty: function () {
 
 			return _.keys(this.content).length === 0;
@@ -320,7 +337,7 @@ modulejs.define('model/entry', ['_', 'core/types', 'core/ajax', 'core/event'], f
 		}
 	});
 
-	return window.ENTRY = {
+	return {
 		get: getEntry,
 		remove: removeEntry
 	};
diff --git a/src/_h5ai/js/inc/parser/apache-autoindex.js b/src/_h5ai/js/inc/parser/apache-autoindex.js
index 5123aeed..4190512c 100644
--- a/src/_h5ai/js/inc/parser/apache-autoindex.js
+++ b/src/_h5ai/js/inc/parser/apache-autoindex.js
@@ -1,5 +1,5 @@
 
-modulejs.define('parser/apache-autoindex', ['_', '$', 'core/settings', 'core/format', 'model/entry'], function (_, $, settings, format, Entry) {
+modulejs.define('parser/apache-autoindex', ['_', '$', 'core/mode', 'core/settings', 'core/format', 'model/entry'], function (_, $, mode, settings, format, Entry) {
 
 	var parseTableRow = function (absHref, tr) {
 
@@ -35,13 +35,13 @@ modulejs.define('parser/apache-autoindex', ['_', '$', 'core/settings', 'core/for
 			return parseTable(absHref, $id.find('table'));
 		};
 
+	mode.id = 'aai';
+	mode.dataType = 'apache-autoindex';
+	mode.serverName = 'apache';
+	mode.serverVersion = null;
+
 	return {
-		id: 'apache-autoindex',
-		mode: 'aai',
-		server: {
-			name: 'apache',
-			version: null
-		},
+		dataType: 'apache-autoindex',
 		parse: parse
 	};
 });
diff --git a/src/_h5ai/js/inc/parser/generic-json.js b/src/_h5ai/js/inc/parser/generic-json.js
index eece589a..df7bcd5d 100644
--- a/src/_h5ai/js/inc/parser/generic-json.js
+++ b/src/_h5ai/js/inc/parser/generic-json.js
@@ -1,16 +1,11 @@
 
-modulejs.define('parser/generic-json', ['_', '$', 'core/settings', 'model/entry'], function (_, $, settings, Entry) {
+modulejs.define('parser/generic-json', ['_', '$', 'core/mode', 'core/settings', 'model/entry'], function (_, $, mode, settings, Entry) {
 
-	var parser = {
-			id: 'generic-json',
-			mode: null,
-			server: {
-				name: null,
-				version: null
-			}
-		},
+	var parseJson = function (absHref, json) {
 
-		parseJson = function (absHref, json) {
+			mode.id = json.id;
+			mode.serverName = json.serverName;
+			mode.serverVersion = json.serverVersion;
 
 			if (_.has(json, 'customHeader')) {
 				settings.custom.header = json.customHeader;
@@ -18,13 +13,6 @@ modulejs.define('parser/generic-json', ['_', '$', 'core/settings', 'model/entry'
 			if (_.has(json, 'customFooter')) {
 				settings.custom.footer = json.customFooter;
 			}
-			if (_.has(json, 'mode')) {
-				parser.mode = json.mode;
-			}
-			if (_.has(json, 'server')) {
-				parser.server = json.server;
-			}
-
 			return _.map(json.entries, function (jsonEntry) {
 
 				return Entry.get(jsonEntry.absHref, jsonEntry.time, jsonEntry.size, jsonEntry.status, jsonEntry.content);
@@ -49,7 +37,10 @@ modulejs.define('parser/generic-json', ['_', '$', 'core/settings', 'model/entry'
 			return parseJsonStr(absHref, $id.text());
 		};
 
-	parser.parse = parse;
+	mode.dataType = 'generic-json';
 
-	return parser;
+	return {
+		dataType: 'generic-json',
+		parse: parse
+	};
 });
diff --git a/src/_h5ai/php/inc/Entry.php b/src/_h5ai/php/inc/Entry.php
index 85101309..d9aab195 100644
--- a/src/_h5ai/php/inc/Entry.php
+++ b/src/_h5ai/php/inc/Entry.php
@@ -8,6 +8,12 @@ class Entry {
 	private static $cache = array();
 
 
+	private static function startsWith($sequence, $part) {
+
+		return (substr($sequence, 0, strlen($part)) === $part);
+	}
+
+
 	public static function get_cache() {
 
 		return Entry::$cache;
@@ -16,6 +22,11 @@ class Entry {
 
 	public static function get($h5ai, $absPath, $absHref) {
 
+		if (!Entry::startsWith($absHref, $h5ai->getRootAbsHref())) {
+			error_log("ILLEGAL REQUEST: " . $absHref . ", " . $absPath . ", " . $h5ai->getRootAbsHref());
+			return null;
+		}
+
 		if (array_key_exists($absHref, Entry::$cache)) {
 			return Entry::$cache[$absHref];
 		}
@@ -63,8 +74,9 @@ class Entry {
 		}
 
 		$this->parent = null;
-		if ($this->absHref !== "/") {
-			$this->parent = Entry::get($this->h5ai, H5ai::normalize_path(dirname($this->absPath)), H5ai::normalize_path(dirname($this->absHref), true));
+		$parentAbsHref = H5ai::normalize_path(dirname($this->absHref), true);
+		if ($this->absHref !== "/" && Entry::startsWith($parentAbsHref, $h5ai->getRootAbsHref())) {
+			$this->parent = Entry::get($this->h5ai, H5ai::normalize_path(dirname($this->absPath)), $parentAbsHref);
 		}
 
 		$this->isContentFetched = false;
diff --git a/src/_h5ai/php/inc/H5ai.php b/src/_h5ai/php/inc/H5ai.php
index b0029ebd..b94defbb 100644
--- a/src/_h5ai/php/inc/H5ai.php
+++ b/src/_h5ai/php/inc/H5ai.php
@@ -56,9 +56,9 @@ class H5ai {
 		$this->requested_from = H5ai::normalize_path($requested_from);
 
 		$this->h5aiAbsPath = H5ai::normalize_path(H5AI_ABS_PATH);
+		$this->rootAbsPath = H5ai::normalize_path(dirname(H5AI_ABS_PATH));
 
 		global $H5AI_CONFIG;
-		$this->rootAbsPath = H5ai::normalize_path($H5AI_CONFIG["ROOT_ABS_PATH"]);
 		$this->ignore_names = $H5AI_CONFIG["IGNORE"];
 		$this->ignore_patterns = $H5AI_CONFIG["IGNORE_PATTERNS"];
 		$this->index_files = $H5AI_CONFIG["INDEX_FILES"];
@@ -66,8 +66,8 @@ class H5ai {
 		$this->config = H5ai::load_config($this->h5aiAbsPath . "/config.js");
 		$this->options = $this->config["options"];
 
-		$this->rootAbsHref = H5ai::normalize_path($this->options["rootAbsHref"], true);
 		$this->h5aiAbsHref = H5ai::normalize_path($this->options["h5aiAbsHref"], true);
+		$this->rootAbsHref = H5ai::normalize_path(dirname($this->options["h5aiAbsHref"]), true);
 
 		$this->absHref = H5ai::normalize_path(preg_replace('/[^\\/]*$/', '', getenv("REQUEST_URI")), true);
 		$this->absPath = $this->getAbsPath($this->absHref);
@@ -275,14 +275,12 @@ class H5ai {
 		$footer = $this->fileExists($footer ? $this->absPath . "/" . $footer : null) ? $footer : null;
 
 		$json = array(
-			"entries" => $entries,
+			"id" => $this->requested_from === $this->h5aiAbsPath . "/php/h5ai-index.php" ? "php" : "idx.php",
+			"serverName" => strtolower(preg_replace("/\\/.*$/", "", getenv("SERVER_SOFTWARE"))),
+			"serverVersion" => strtolower(preg_replace("/^.*\\//", "", preg_replace("/\\s.*$/", "", getenv("SERVER_SOFTWARE")))),
 			"customHeader" => $header,
 			"customFooter" => $footer,
-			"mode" => $this->requested_from === $this->h5aiAbsPath . "/php/h5ai-index.php" ? "php" : "idx.php",
-			"server" => array(
-				"name" => strtolower(preg_replace("/\\/.*$/", "", getenv("SERVER_SOFTWARE"))),
-				"version" => strtolower(preg_replace("/^.*\\//", "", preg_replace("/\\s.*$/", "", getenv("SERVER_SOFTWARE"))))
-			)
+			"entries" => $entries
 		);
 
 		return json_encode($json) . "\n";