using System.Collections.Generic; using System.IO; using System.Xml; namespace AllocsFixes.NetConnections.Servers.Web { public class WebPermissions { private const string PERMISSIONS_FILE = "webpermissions.xml"; private static WebPermissions instance; private readonly WebModulePermission defaultModulePermission = new WebModulePermission ("", 0); private readonly Dictionary knownModules = new Dictionary (); private Dictionary admintokens; private FileSystemWatcher fileWatcher; private Dictionary modules; public WebPermissions () { Directory.CreateDirectory (GetFilePath ()); InitFileWatcher (); Load (); } public static WebPermissions Instance { get { lock (typeof (WebPermissions)) { if (instance == null) { instance = new WebPermissions (); } return instance; } } } public bool ModuleAllowedWithLevel (string _module, int _level) { WebModulePermission permInfo = GetModulePermission (_module); return permInfo.permissionLevel >= _level; } 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.ContainsKey (_module.ToLower ())) { return modules [_module.ToLower ()]; } return defaultModulePermission; } // 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.Values.CopyTo (result, 0); return result; } // Commands public void AddModulePermission (string _module, int _permissionLevel, bool _save = true) { WebModulePermission p = new WebModulePermission (_module.ToLower (), _permissionLevel); lock (this) { modules [_module] = p; if (_save) { Save (); } } } public void AddKnownModule (string _module, int _defaultPermission) { if (!string.IsNullOrEmpty (_module)) { lock (this) { if (!IsKnownModule (_module)) { knownModules.Add (_module, new WebModulePermission (_module, _defaultPermission)); } if (_defaultPermission > 0 && !modules.ContainsKey (_module.ToLower ())) { AddModulePermission (_module, _defaultPermission); } } } } public bool IsKnownModule (string _module) { if (!string.IsNullOrEmpty (_module)) { lock (this) { return knownModules.ContainsKey (_module); } } return false; } public void RemoveModulePermission (string _module, bool _save = true) { lock (this) { modules.Remove (_module.ToLower ()); if (_save) { Save (); } } } public List GetModules () { List result = new List (); foreach (string module in knownModules.Keys) { if (modules.ContainsKey (module)) { result.Add (modules [module]); } else { result.Add (knownModules [module]); } } return result; } //IO Tasks private void InitFileWatcher () { fileWatcher = new FileSystemWatcher (GetFilePath (), GetFileName ()); fileWatcher.Changed += OnFileChanged; fileWatcher.Created += OnFileChanged; fileWatcher.Deleted += OnFileChanged; fileWatcher.EnableRaisingEvents = true; } private void OnFileChanged (object source, FileSystemEventArgs e) { Log.Out ("Reloading " + PERMISSIONS_FILE); Load (); } private string GetFilePath () { return GamePrefs.GetString (EnumGamePrefs.SaveGameFolder); } private string GetFileName () { return PERMISSIONS_FILE; } private string GetFullPath () { return GetFilePath () + "/" + GetFileName (); } public void Load () { admintokens = new Dictionary (); modules = new Dictionary (); if (!Utils.FileExists (GetFullPath ())) { Log.Out (string.Format ("Permissions file '{0}' not found, creating.", GetFileName ())); Save (); return; } Log.Out (string.Format ("Loading permissions file at '{0}'", GetFullPath ())); XmlDocument xmlDoc = new XmlDocument (); try { xmlDoc.Load (GetFullPath ()); } catch (XmlException e) { Log.Error (string.Format ("Failed loading permissions file: {0}", e.Message)); return; } XmlNode adminToolsNode = xmlDoc.DocumentElement; 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"); int permissionLevel = 2000; if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out 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; } int permissionLevel = 0; if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out permissionLevel)) { Log.Warning ( "Ignoring permission-entry because of invalid (non-numeric) value for 'permission_level' attribute: " + subChild.OuterXml); continue; } AddModulePermission (lineItem.GetAttribute ("module").ToLower (), permissionLevel, false); } } } Log.Out ("Loading permissions file done."); } public void Save () { fileWatcher.EnableRaisingEvents = false; using (StreamWriter sw = new StreamWriter (GetFullPath ())) { sw.WriteLine (""); sw.WriteLine (""); sw.WriteLine (); sw.WriteLine (" "); sw.WriteLine ( " "); foreach (AdminToken at in admintokens.Values) { sw.WriteLine (" ", at.name, at.token, at.permissionLevel); } sw.WriteLine (" "); sw.WriteLine (); sw.WriteLine (" "); foreach (WebModulePermission wap in modules.Values) { sw.WriteLine (" ", wap.module, wap.permissionLevel); } sw.WriteLine (" "); sw.WriteLine (); sw.WriteLine (" "); sw.WriteLine ( " "); sw.WriteLine (); sw.WriteLine (" "); sw.WriteLine (" "); sw.WriteLine (); sw.WriteLine ( " "); sw.WriteLine (" "); sw.WriteLine (); sw.WriteLine (" "); sw.WriteLine (" "); sw.WriteLine (); sw.WriteLine (" "); sw.WriteLine (); sw.WriteLine (" "); sw.WriteLine (" "); sw.WriteLine (" "); sw.WriteLine (); sw.WriteLine (""); sw.Flush (); sw.Close (); } fileWatcher.EnableRaisingEvents = true; } public class AdminToken { public string name; public int permissionLevel; public string token; public AdminToken (string _name, string _token, int _permissionLevel) { name = _name; token = _token; permissionLevel = _permissionLevel; } } public struct WebModulePermission { public string module; public int permissionLevel; public WebModulePermission (string _module, int _permissionLevel) { module = _module; permissionLevel = _permissionLevel; } } } }