Index: binary-improvements2/WebServer/src/WebPermissions.cs
===================================================================
--- binary-improvements2/WebServer/src/WebPermissions.cs	(revision 394)
+++ binary-improvements2/WebServer/src/WebPermissions.cs	(revision 395)
@@ -6,22 +6,50 @@
 namespace Webserver {
 	public class WebPermissions {
-		private const string permissionsFile = "webpermissions.xml";
+		private const string permissionsFileName = "webpermissions.xml";
 		private static WebPermissions instance;
+
+		private readonly FileSystemWatcher fileWatcher;
+
 		private readonly WebModulePermission defaultModulePermission = new WebModulePermission ("", 0);
 
-		private readonly Dictionary<string, WebModulePermission> knownModules =
+		/// <summary>
+		///  Registered user/pass admin tokens
+		/// </summary>
+		private readonly Dictionary<string, AdminToken> adminTokens = new CaseInsensitiveStringDictionary<AdminToken> ();
+
+		/// <summary>
+		/// Contains all registered modules and their default permission
+		/// </summary>
+		private readonly Dictionary<string, WebModulePermission> knownModules = new CaseInsensitiveStringDictionary<WebModulePermission> ();
+
+		/// <summary>
+		/// Manually defined module permissions
+		/// </summary>
+		private readonly Dictionary<string, WebModulePermission> modulePermissions =
 			new CaseInsensitiveStringDictionary<WebModulePermission> ();
 
-		private readonly Dictionary<string, AdminToken> admintokens = new CaseInsensitiveStringDictionary<AdminToken> ();
-		private FileSystemWatcher fileWatcher;
-
-		private readonly Dictionary<string, WebModulePermission> modules = new CaseInsensitiveStringDictionary<WebModulePermission> ();
+		/// <summary>
+		/// Public list of all modules, both those with custom permissions as well as those that do not with their default permission
+		/// </summary>
+		private readonly List<WebModulePermission> allModulesList = new List<WebModulePermission> ();
+
+		private readonly ReadOnlyCollection<WebModulePermission> allModulesListRo;
+
+		private static string SettingsFilePath => GamePrefs.GetString (EnumUtils.Parse<EnumGamePrefs> ("SaveGameFolder"));
+		private static string SettingsFileName => permissionsFileName;
+		private static string SettingsFullPath => SettingsFilePath + "/" + SettingsFileName;
 
 		private WebPermissions () {
-			allModulesList = new List<WebModulePermission> ();
 			allModulesListRo = new ReadOnlyCollection<WebModulePermission> (allModulesList);
-			Directory.CreateDirectory (GetFilePath ());
-			InitFileWatcher ();
+
+			Directory.CreateDirectory (SettingsFilePath);
+
 			Load ();
+
+			fileWatcher = new FileSystemWatcher (SettingsFilePath, SettingsFileName);
+			fileWatcher.Changed += OnFileChanged;
+			fileWatcher.Created += OnFileChanged;
+			fileWatcher.Deleted += OnFileChanged;
+			fileWatcher.EnableRaisingEvents = true;
 		}
 
@@ -34,4 +62,107 @@
 		}
 
+
+#region Admin Tokens
+
+		public void AddAdmin (string _name, string _token, int _permissionLevel, bool _save = true) {
+			AdminToken c = new AdminToken (_name, _token, _permissionLevel);
+			lock (this) {
+				adminTokens [_name] = c;
+				if (_save) {
+					Save ();
+				}
+			}
+		}
+
+		public void RemoveAdmin (string _name, bool _save = true) {
+			lock (this) {
+				adminTokens.Remove (_name);
+				if (_save) {
+					Save ();
+				}
+			}
+		}
+
+		public bool IsAdmin (string _name) {
+			return adminTokens.ContainsKey (_name);
+		}
+
+		public AdminToken[] GetAdmins () {
+			AdminToken[] result = new AdminToken[adminTokens.Count];
+			adminTokens.CopyValuesTo (result);
+			return result;
+		}
+
+		public AdminToken GetWebAdmin (string _name, string _token) {
+			if (IsAdmin (_name) && adminTokens [_name].token == _token) {
+				return adminTokens [_name];
+			}
+
+			return null;
+		}
+
+#endregion
+
+
+#region Modules
+
+		public void AddModulePermission (string _module, int _permissionLevel, bool _save = true) {
+			WebModulePermission p = new WebModulePermission (_module, _permissionLevel);
+			lock (this) {
+				allModulesList.Clear ();
+				modulePermissions [_module] = p;
+				if (_save) {
+					Save ();
+				}
+			}
+		}
+
+		public void AddKnownModule (string _module, int _defaultPermission) {
+			if (string.IsNullOrEmpty (_module)) {
+				return;
+			}
+
+			WebModulePermission p = new WebModulePermission (_module, _defaultPermission);
+
+			lock (this) {
+				allModulesList.Clear ();
+				knownModules [_module] = p;
+			}
+		}
+
+		public bool IsKnownModule (string _module) {
+			if (string.IsNullOrEmpty (_module)) {
+				return false;
+			}
+
+			lock (this) {
+				return knownModules.ContainsKey (_module);
+			}
+		}
+
+		public void RemoveModulePermission (string _module, bool _save = true) {
+			lock (this) {
+				allModulesList.Clear ();
+				modulePermissions.Remove (_module);
+				if (_save) {
+					Save ();
+				}
+			}
+		}
+
+		public IList<WebModulePermission> GetModules () {
+			if (allModulesList.Count != 0) {
+				return allModulesListRo;
+			}
+
+			foreach ((string moduleName, WebModulePermission moduleDefaultPerm) in knownModules) {
+				allModulesList.Add (modulePermissions.TryGetValue (moduleName, out WebModulePermission modulePermission)
+					? modulePermission
+					: moduleDefaultPerm);
+			}
+
+			return allModulesListRo;
+		}
+
 		public bool ModuleAllowedWithLevel (string _module, int _level) {
 			WebModulePermission permInfo = GetModulePermission (_module);
@@ -39,14 +170,6 @@
 		}
 
-		public AdminToken GetWebAdmin (string _name, string _token) {
-			if (IsAdmin (_name) && admintokens [_name].token == _token) {
-				return admintokens [_name];
-			}
-
-			return null;
-		}
-
 		public WebModulePermission GetModulePermission (string _module) {
-			if (modules.TryGetValue (_module, out WebModulePermission result)) {
+			if (modulePermissions.TryGetValue (_module, out WebModulePermission result)) {
 				return result;
 			}
@@ -55,143 +178,30 @@
 		}
 
-
-		// Admins
-		public void AddAdmin (string _name, string _token, int _permissionLevel, bool _save = true) {
-			AdminToken c = new AdminToken (_name, _token, _permissionLevel);
-			lock (this) {
-				admintokens [_name] = c;
-				if (_save) {
-					Save ();
-				}
-			}
-		}
-
-		public void RemoveAdmin (string _name, bool _save = true) {
-			lock (this) {
-				admintokens.Remove (_name);
-				if (_save) {
-					Save ();
-				}
-			}
-		}
-
-		public bool IsAdmin (string _name) {
-			return admintokens.ContainsKey (_name);
-		}
-
-		public AdminToken[] GetAdmins () {
-			AdminToken[] result = new AdminToken[admintokens.Count];
-			admintokens.CopyValuesTo (result);
-			return result;
-		}
-
-
-		// Commands
-		public void AddModulePermission (string _module, int _permissionLevel, bool _save = true) {
-			WebModulePermission p = new WebModulePermission (_module, _permissionLevel);
-			lock (this) {
-				allModulesList.Clear ();
-				modules [_module] = p;
-				if (_save) {
-					Save ();
-				}
-			}
-		}
-
-		public void AddKnownModule (string _module, int _defaultPermission) {
-			if (string.IsNullOrEmpty (_module)) {
-				return;
-			}
-			
-			WebModulePermission p = new WebModulePermission (_module, _defaultPermission);
-
-			lock (this) {
-				allModulesList.Clear ();
-				knownModules [_module] = p;
-			}
-		}
-
-		public bool IsKnownModule (string _module) {
-			if (string.IsNullOrEmpty (_module)) {
-				return false;
-			}
-
-			lock (this) {
-				return knownModules.ContainsKey (_module);
-			}
-
-		}
-
-		public void RemoveModulePermission (string _module, bool _save = true) {
-			lock (this) {
-				allModulesList.Clear ();
-				modules.Remove (_module);
-				if (_save) {
-					Save ();
-				}
-			}
-		}
-
-		private readonly List<WebModulePermission> allModulesList;
-		private readonly ReadOnlyCollection<WebModulePermission> allModulesListRo; 
-
-		public IList<WebModulePermission> GetModules () {
-			if (allModulesList.Count != 0) {
-				return allModulesListRo;
-			}
-
-			foreach ((string moduleName, WebModulePermission moduleDefaultPerm) in knownModules) {
-				allModulesList.Add (modules.TryGetValue (moduleName, out WebModulePermission modulePermission)
-					? modulePermission
-					: moduleDefaultPerm);
-			}
-
-			return allModulesListRo;
-		}
-
-
-		//IO Tasks
-
-		private void InitFileWatcher () {
-			fileWatcher = new FileSystemWatcher (GetFilePath (), GetFileName ());
-			fileWatcher.Changed += OnFileChanged;
-			fileWatcher.Created += OnFileChanged;
-			fileWatcher.Deleted += OnFileChanged;
-			fileWatcher.EnableRaisingEvents = true;
-		}
+#endregion
+
+
+#region IO Tasks
 
 		private void OnFileChanged (object _source, FileSystemEventArgs _e) {
-			Log.Out ("Reloading " + permissionsFile);
+			Log.Out ("Reloading " + SettingsFileName);
 			Load ();
 		}
 
-		private static string GetFilePath () {
-			return GamePrefs.GetString (EnumUtils.Parse<EnumGamePrefs> ("SaveGameFolder"));
-		}
-
-		private static string GetFileName () {
-			return permissionsFile;
-		}
-
-		private static string GetFullPath () {
-			return GetFilePath () + "/" + GetFileName ();
-		}
-
 		public void Load () {
-			admintokens.Clear ();
-			modules.Clear ();
-
-			if (!File.Exists (GetFullPath ())) {
-				Log.Out ($"Permissions file '{GetFileName ()}' not found, creating.");
+			adminTokens.Clear ();
+			modulePermissions.Clear ();
+
+			if (!File.Exists (SettingsFullPath)) {
+				Log.Out ($"Permissions file '{SettingsFileName}' not found, creating.");
 				Save ();
 				return;
 			}
 
-			Log.Out ($"Loading permissions file at '{GetFullPath ()}'");
+			Log.Out ($"Loading permissions file at '{SettingsFullPath}'");
 
 			XmlDocument xmlDoc = new XmlDocument ();
 
 			try {
-				xmlDoc.Load (GetFullPath ());
+				xmlDoc.Load (SettingsFullPath);
 			} catch (XmlException e) {
 				Log.Error ("Failed loading permissions file: " + e.Message);
@@ -205,141 +215,125 @@
 				return;
 			}
+
+			foreach (XmlNode childNode in adminToolsNode.ChildNodes) {
+				switch (childNode.Name) {
+					case "admintokens":
+						ParseAdminTokens (childNode);
+						break;
+					case "permissions":
+						ParseModulePermissions (childNode);
+						break;
+				}
+			}
+
+			Log.Out ("Loading permissions file done.");
+		}
+
+		private void ParseAdminTokens (XmlNode _baseNode) {
+			foreach (XmlNode subChild in _baseNode.ChildNodes) {
+				if (subChild.NodeType == XmlNodeType.Comment) {
+					continue;
+				}
+
+				if (subChild.NodeType != XmlNodeType.Element) {
+					Log.Warning ($"Unexpected XML node found in 'admintokens' section: {subChild.OuterXml}");
+					continue;
+				}
+
+				XmlElement lineItem = (XmlElement)subChild;
+
+				if (!lineItem.HasAttribute ("name")) {
+					Log.Warning ($"Ignoring admintoken-entry because of missing 'name' attribute: {subChild.OuterXml}");
+					continue;
+				}
+
+				if (!lineItem.HasAttribute ("token")) {
+					Log.Warning ($"Ignoring admintoken-entry because of missing 'token' attribute: {subChild.OuterXml}");
+					continue;
+				}
+
+				if (!lineItem.HasAttribute ("permission_level")) {
+					Log.Warning ($"Ignoring admintoken-entry because of missing 'permission_level' attribute: {subChild.OuterXml}");
+					continue;
+				}
+
+				string name = lineItem.GetAttribute ("name");
+				string token = lineItem.GetAttribute ("token");
+				if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out int permissionLevel)) {
+					Log.Warning (
+						$"Ignoring admintoken-entry because of invalid (non-numeric) value for 'permission_level' attribute: {subChild.OuterXml}");
+					continue;
+				}
+
+				AddAdmin (name, token, permissionLevel, false);
+			}
+		}
+
+		private void ParseModulePermissions (XmlNode _baseNode) {
+			foreach (XmlNode subChild in _baseNode.ChildNodes) {
+				if (subChild.NodeType == XmlNodeType.Comment) {
+					continue;
+				}
+
+				if (subChild.NodeType != XmlNodeType.Element) {
+					Log.Warning ($"Unexpected XML node found in 'permissions' section: {subChild.OuterXml}");
+					continue;
+				}
+
+				XmlElement lineItem = (XmlElement)subChild;
+
+				if (!lineItem.HasAttribute ("module")) {
+					Log.Warning ($"Ignoring permission-entry because of missing 'module' attribute: {subChild.OuterXml}");
+					continue;
+				}
+
+				if (!lineItem.HasAttribute ("permission_level")) {
+					Log.Warning ($"Ignoring permission-entry because of missing 'permission_level' attribute: {subChild.OuterXml}");
+					continue;
+				}
+
+				if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out int permissionLevel)) {
+					Log.Warning (
+						$"Ignoring permission-entry because of invalid (non-numeric) value for 'permission_level' attribute: {subChild.OuterXml}");
+					continue;
+				}
+
+				AddModulePermission (lineItem.GetAttribute ("module"), permissionLevel, false);
+			}
+		}
+
+		public void Save () {
+			XmlDocument xml = new XmlDocument ();
+
+			xml.CreateXmlDeclaration ();
+
+			// xml.AddXmlComment (XmlHeader);
+
+			XmlElement root = xml.AddXmlElement ("webpermissions");
+
+			// AdminTokens
+			XmlElement adminTokensElem = root.AddXmlElement ("admintokens");
+			adminTokensElem.AddXmlComment (" <token name=\"adminuser1\" token=\"supersecrettoken\" permission_level=\"0\" /> ");
+			foreach ((string _, AdminToken adminToken) in adminTokens) {
+				adminTokensElem.AddXmlElement ("token")
+					.SetAttrib ("name", adminToken.name)
+					.SetAttrib ("token", adminToken.token)
+					.SetAttrib ("permission_level", adminToken.permissionLevel.ToString ());
+			}
+
+			XmlElement modulePermissionsElem = root.AddXmlElement ("permissions");
+			foreach ((string _, WebModulePermission webModulePermission) in modulePermissions) {
+				modulePermissionsElem.AddXmlElement ("permission")
+					.SetAttrib ("module", webModulePermission.module)
+					.SetAttrib ("permission_level", webModulePermission.permissionLevel.ToString ());
+			}
 			
-			foreach (XmlNode childNode in adminToolsNode.ChildNodes) {
-				if (childNode.Name == "admintokens") {
-					foreach (XmlNode subChild in childNode.ChildNodes) {
-						if (subChild.NodeType == XmlNodeType.Comment) {
-							continue;
-						}
-
-						if (subChild.NodeType != XmlNodeType.Element) {
-							Log.Warning ("Unexpected XML node found in 'admintokens' section: " + subChild.OuterXml);
-							continue;
-						}
-
-						XmlElement lineItem = (XmlElement) subChild;
-
-						if (!lineItem.HasAttribute ("name")) {
-							Log.Warning ("Ignoring admintoken-entry because of missing 'name' attribute: " +
-							             subChild.OuterXml);
-							continue;
-						}
-
-						if (!lineItem.HasAttribute ("token")) {
-							Log.Warning ("Ignoring admintoken-entry because of missing 'token' attribute: " +
-							             subChild.OuterXml);
-							continue;
-						}
-
-						if (!lineItem.HasAttribute ("permission_level")) {
-							Log.Warning ("Ignoring admintoken-entry because of missing 'permission_level' attribute: " +
-							             subChild.OuterXml);
-							continue;
-						}
-
-						string name = lineItem.GetAttribute ("name");
-						string token = lineItem.GetAttribute ("token");
-						if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out int permissionLevel)) {
-							Log.Warning (
-								"Ignoring admintoken-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
-								subChild.OuterXml);
-							continue;
-						}
-
-						AddAdmin (name, token, permissionLevel, false);
-					}
-				}
-
-				if (childNode.Name == "permissions") {
-					foreach (XmlNode subChild in childNode.ChildNodes) {
-						if (subChild.NodeType == XmlNodeType.Comment) {
-							continue;
-						}
-
-						if (subChild.NodeType != XmlNodeType.Element) {
-							Log.Warning ("Unexpected XML node found in 'permissions' section: " + subChild.OuterXml);
-							continue;
-						}
-
-						XmlElement lineItem = (XmlElement) subChild;
-
-						if (!lineItem.HasAttribute ("module")) {
-							Log.Warning ("Ignoring permission-entry because of missing 'module' attribute: " +
-							             subChild.OuterXml);
-							continue;
-						}
-
-						if (!lineItem.HasAttribute ("permission_level")) {
-							Log.Warning ("Ignoring permission-entry because of missing 'permission_level' attribute: " +
-							             subChild.OuterXml);
-							continue;
-						}
-
-						if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out int permissionLevel)) {
-							Log.Warning (
-								"Ignoring permission-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
-								subChild.OuterXml);
-							continue;
-						}
-
-						AddModulePermission (lineItem.GetAttribute ("module"), permissionLevel, false);
-					}
-				}
-			}
-
-			Log.Out ("Loading permissions file done.");
-		}
-
-		public void Save () {
+
 			fileWatcher.EnableRaisingEvents = false;
-
-			using (StreamWriter sw = new StreamWriter (GetFullPath ())) {
-				sw.WriteLine ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-				sw.WriteLine ("<webpermissions>");
-				sw.WriteLine ();
-				sw.WriteLine ("	<admintokens>");
-				sw.WriteLine (
-					"		<!-- <token name=\"adminuser1\" token=\"supersecrettoken\" permission_level=\"0\" /> -->");
-				foreach ((var _, AdminToken adminToken) in admintokens) {
-					sw.WriteLine ($"		<token name=\"{adminToken.name}\" token=\"{adminToken.token}\" permission_level=\"{adminToken.permissionLevel}\" />");
-				}
-
-				sw.WriteLine ("	</admintokens>");
-				sw.WriteLine ();
-				sw.WriteLine ("	<permissions>");
-				foreach ((var _, WebModulePermission webModulePermission) in modules) {
-					sw.WriteLine ($"		<permission module=\"{webModulePermission.module}\" permission_level=\"{webModulePermission.permissionLevel}\" />");
-				}
-
-				sw.WriteLine ("		<!-- <permission module=\"web.map\" permission_level=\"1000\" /> -->");
-				sw.WriteLine ();
-				sw.WriteLine ("		<!-- <permission module=\"webapi.getlog\" permission_level=\"0\" /> -->");
-				sw.WriteLine (
-					"		<!-- <permission module=\"webapi.executeconsolecommand\" permission_level=\"0\" /> -->");
-				sw.WriteLine ();
-				sw.WriteLine ("		<!-- <permission module=\"webapi.getstats\" permission_level=\"1000\" /> -->");
-				sw.WriteLine ("		<!-- <permission module=\"webapi.getplayersonline\" permission_level=\"1000\" /> -->");
-				sw.WriteLine ();
-				sw.WriteLine (
-					"		<!-- <permission module=\"webapi.getplayerslocation\" permission_level=\"1000\" /> -->");
-				sw.WriteLine ("		<!-- <permission module=\"webapi.viewallplayers\" permission_level=\"1\" /> -->");
-				sw.WriteLine ();
-				sw.WriteLine ("		<!-- <permission module=\"webapi.getlandclaims\" permission_level=\"1000\" /> -->");
-				sw.WriteLine ("		<!-- <permission module=\"webapi.viewallclaims\" permission_level=\"1\" /> -->");
-				sw.WriteLine ();
-				sw.WriteLine ("		<!-- <permission module=\"webapi.getplayerinventory\" permission_level=\"1\" /> -->");
-				sw.WriteLine ();
-				sw.WriteLine ("		<!-- <permission module=\"webapi.gethostilelocation\" permission_level=\"1\" /> -->");
-				sw.WriteLine ("		<!-- <permission module=\"webapi.getanimalslocation\" permission_level=\"1\" /> -->");
-				sw.WriteLine ("	</permissions>");
-				sw.WriteLine ();
-				sw.WriteLine ("</webpermissions>");
-
-				sw.Flush ();
-				sw.Close ();
-			}
-
+			xml.Save (SettingsFullPath);
 			fileWatcher.EnableRaisingEvents = true;
 		}
+
+#endregion
 
 
