Exemple #1
0
        internal static bool GetCorrectFileName(DatabaseDaemon __instance, object obj, ref string __result)
        {
            if (obj is ElementInfo info)
            {
                switch (info.Name)
                {
                case "GitCommitEntry":
                    __result =
                        $"Commit#{int.Parse(info.Children.GetElement("EntryNumber").Content):000}{(info.Children.GetElement("SourceIP").Content.StartsWith("192.168.1.1") ? "" : "*")}";
                    break;

                case "Person":
                    __result = __instance.GetFilenameForPersonName(info.Children.GetElement("firstName").Content, info.Children.GetElement("lastName").Content);
                    return(false);

                default:
                    __result = info.Name.Replace(" ", "_").ToLower();
                    break;
                }

                __result = Utils.GetNonRepeatingFilename(__result, ".rec", __instance.DatasetFolder);
                return(false);
            }

            return(true);
        }
 public static List <DataInfo> GetDataset(this DatabaseDaemon daemon)
 {
     if (!databaseDatasets.ContainsKey(daemon))
     {
         databaseDatasets.Add(daemon, new List <DataInfo>());
     }
     return(databaseDatasets[daemon]);
 }
        public static void InitDataset(this DatabaseDaemon daemon)
        {
            if (!databaseDatasets.ContainsKey(daemon))
            {
                databaseDatasets.Add(daemon, new List <DataInfo>());
            }

            bool isVehicleInfo;

            if (databaseDatasets[daemon]?.Count >= 1)
            {
                foreach (var contents in databaseDatasets[daemon])
                {
                    var contentStr = contents.ToString();
                    daemon.DatasetFolder.AddFile(daemon.GetDatabaseFilename(contentStr), contentStr);
                }
            }
            else if (People.all.Count < 1)
            {
                ;
            }
            else if (isVehicleInfo = daemon.DataTypeIdentifier.EndsWith("VehicleInfo") || daemon.DataTypeIdentifier.EndsWith("Person"))
            {
                daemon.FilenameIsPersonName = true;
                foreach (var p in People.all)
                {
                    if (p.vehicles.Count > 0)
                    {
                        daemon.DatasetFolder.AddFile(daemon.GetDatabasePersonalFilename(p),
                                                     isVehicleInfo
                                                     ? string.Join("\n", p.vehicles.Select((v) => v.ToXml()))
                                                     : p.ToXml());
                    }
                }
            }
            else if (daemon.DataTypeIdentifier.EndsWith("NeopalsAccount"))
            {
                daemon.FilenameIsPersonName = false;
                daemon.HasSpecialCaseDraw   = true;
                foreach (var p in People.all)
                {
                    if (p.NeopalsAccount != null)
                    {
                        var contentStr = p.ToXml();
                        daemon.DatasetFolder.AddFile(daemon.GetDatabaseFilename(contentStr), contentStr);
                    }
                }
            }
        }
Exemple #4
0
        /* Computer.load */
        private static Computer LoadComputer(ElementInfo root, OS os)
        {
            /* Read top-level */

            var compName    = root.Attributes.GetValue("name");
            var compIP      = root.Attributes.GetValue("ip");
            var compType    = root.Attributes.GetByte("type");
            var compSpec    = root.Attributes.GetValue("spec");
            var compID      = root.Attributes.GetValue("id");
            var compDevices = root.Attributes.GetValueOrDefault("devices", null);
            var compIcon    = root.Attributes.GetValueOrDefault("icon", null);
            var compTracker = root.Attributes.GetBool("tracker");

            /* negative zeros chosen because they're unlikely to show up by accident */
            var compX = -0f;
            var compY = -0f;

            Computer result   = null;
            var      executor = new ParsedTreeExecutor(true);

            executor.AddExecutor("location", (exec, info) =>
            {
                compX = info.Attributes.GetFloat("x");
                compY = info.Attributes.GetFloat("y");
            });

            executor.AddExecutor("security", (exec, info) =>
            {
                var secLevel = info.Attributes.GetInt("level");

                /* HACK: This is THE EARLIEST we can construct the Computer instance */
                /* and other things rely on it being there, so we better get it done fast. */
                result = new Computer(compName, compIP, new Vector2(compX, compY), secLevel, compType, os)
                {
                    /* apply whatever else we've parsed so far */
                    idName             = compID,
                    attatchedDeviceIDs = compDevices,
                    icon       = compIcon,
                    HasTracker = compTracker,
                    firewall   = null, /* may be overwritten later */

                    /* now apply *our* attributes */
                    traceTime           = info.Attributes.GetFloat("traceTime"),
                    portsNeededForCrack = info.Attributes.GetInt("portsToCrack"),
                    adminIP             = info.Attributes.GetValue("adminIP")
                };

                var proxyTime = info.Attributes.GetFloat("proxyTime");
                if (proxyTime > 0.0)
                {
                    result.addProxy(proxyTime);
                }
                else
                {
                    result.hasProxy    = false;
                    result.proxyActive = false;
                }
            });

            executor.AddExecutor("admin", (exec, info) =>
            {
                Administrator admin = null;
                switch (info.Attributes.GetValue("type"))
                {
                case "fast":
                    admin = new FastBasicAdministrator();
                    break;

                case "basic":
                    admin = new BasicAdministrator();
                    break;

                case "progress":
                    admin = new FastProgressOnlyAdministrator();
                    break;
                }

                if (admin != null)
                {
                    admin.ResetsPassword = info.Attributes.GetBool("resetPass");
                    admin.IsSuper        = info.Attributes.GetBool("isSuper");
                }

                result.admin = admin;
            });

            executor.AddExecutor("links", (exec, info) =>
            {
                foreach (string idxStr in info.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries))
                {
                    result.links.Add(Convert.ToInt32(idxStr));
                }
            }, true);

            executor.AddExecutor("firewall", (exec, info) =>
                                 result.firewall = new Firewall(
                                     info.Attributes.GetInt("complexity"),
                                     info.Attributes.GetValueOrDefault("solution", null),
                                     info.Attributes.GetFloat("additionalDelay")
                                     )
                                 );

            executor.AddExecutor("portsOpen", (exec, info) =>
            {
                if (info.Value.Length > 0)
                {
                    ComputerLoader.loadPortsIntoComputer(info.Value, result);
                }
            }, true);

            executor.AddExecutor("portRemap", (exec, info) =>
                                 result.PortRemapping = PortRemappingSerializer.Deserialize(info.Value), true);

            executor.AddExecutor("users", (exec, info) =>
            {
                foreach (var userData in info.Children.Where(e => e.Name == "user"))
                {
                    string userName = userData.Attributes.GetValue("name");
                    string userPass = userData.Attributes.GetValue("pass");
                    var user        = new UserDetail(
                        userName,
                        userPass,
                        userData.Attributes.GetByte("type")
                        )
                    {
                        known = userData.Attributes.GetBool("known")
                    };

                    if (userName.ToLower() == "admin")
                    {
                        result.adminPass = userPass;
                    }

                    result.users.Add(user);
                }
            }, true);

            executor.AddExecutor("Memory", (exec, info) =>
                                 result.Memory = ReplacementsCommon.LoadMemoryContents(info), true);

            #region Daemons

            executor.AddExecutor("daemons.MailServer", (exec, info) =>
            {
                var server = result.AddDaemon <MailServer>(info.Attributes.GetValue("name"), os);
                if (info.Attributes.TryGetValue("color", out var colorStr))
                {
                    var color = Utility.GetColorFromString(colorStr, true, null);
                    if (color.HasValue)
                    {
                        server.setThemeColor(color.Value);
                    }
                }
            });

            executor.AddExecutor("daemons.MissionListingServer", (exec, info) =>
            {
                var serviceName       = info.Attributes.GetValue("name");
                var group             = info.Attributes.GetValue("group");
                var isPublic          = info.Attributes.GetBool("public");
                var isAssign          = info.Attributes.GetBool("assign");
                var title             = info.Attributes.GetValueOrDefault("title", null);
                var iconPath          = info.Attributes.GetValueOrDefault("icon", null);
                var input             = info.Attributes.GetValueOrDefault("color", null);
                var articleFolderPath = info.Attributes.GetValueOrDefault("articles", null);

                MissionListingServer server;
                if (iconPath == null || input == null)
                {
                    server = result.AddDaemon <MissionListingServer>(serviceName, group, os, isPublic, isAssign);
                }
                else
                {
                    server = result.AddDaemon <MissionListingServer>(
                        serviceName,
                        iconPath,
                        articleFolderPath,
                        Utils.convertStringToColor(input),
                        os,
                        isPublic,
                        isAssign
                        );
                }
                if (title != null)
                {
                    server.listingTitle = title;
                }
            });

            executor.AddExecutor("daemons.AddEmailServer", (exec, info) =>
                                 result.AddDaemon <AddEmailDaemon>(info.Attributes.GetValue("name"), os));

            executor.AddExecutor("daemons.MessageBoard", (exec, info) =>
            {
                var daemon  = result.AddDaemon <MessageBoardDaemon>(os);
                daemon.name = info.Attributes.GetValue("name");
                if (info.Attributes.TryGetValue("boardName", out var boardName))
                {
                    daemon.BoardName = boardName;
                }
            });

            executor.AddExecutor("daemons.WebServer", (exec, info) =>
                                 result.AddDaemon <WebServerDaemon>(info.Attributes.GetValue("name"), os,
                                                                    info.Attributes.GetValue("url")));

            executor.AddExecutor("daemons.OnlineWebServer", (exec, info) =>
            {
                var daemon = result.AddDaemon <OnlineWebServerDaemon>(info.Attributes.GetValue("name"), os);
                daemon.setURL(info.Attributes.GetValue("url"));
            });

            /* not my typo */
            executor.AddExecutor("daemons.AcademicDatabse", (exec, info) =>
                                 result.AddDaemon <AcademicDatabaseDaemon>(info.Attributes.GetValue("name"), os));

            executor.AddExecutor("daemons.MissionHubServer", (exec, info) =>
                                 result.AddDaemon <MissionHubServer>("unknown", "unknown", os));

            executor.AddExecutor("daemons.DeathRowDatabase", (exec, info) =>
                                 result.AddDaemon <DeathRowDatabaseDaemon>("Death Row Database", os));

            executor.AddExecutor("daemons.MedicalDatabase", (exec, info) =>
                                 result.AddDaemon <MedicalDatabaseDaemon>(os));

            executor.AddExecutor("daemons.HeartMonitor", (exec, info) =>
            {
                var daemon       = result.AddDaemon <HeartMonitorDaemon>(os);
                daemon.PatientID = info.Attributes.GetValueOrDefault("patient", "UNKNOWN");
            });

            executor.AddExecutor("daemons.PointClicker", (exec, info) =>
                                 result.AddDaemon <PointClickerDaemon>("Point Clicker!", os));

            executor.AddExecutor("daemons.ispSystem", (exec, info) =>
                                 result.AddDaemon <ISPDaemon>(os));

            executor.AddExecutor("daemons.porthackheart", (exec, info) =>
                                 result.AddDaemon <PorthackHeartDaemon>(os));

            executor.AddExecutor("daemons.SongChangerDaemon", (exec, info) =>
                                 result.AddDaemon <SongChangerDaemon>(os));

            executor.AddExecutor("daemons.UploadServerDaemon", (exec, info) =>
            {
                var daemon = result.AddDaemon <UploadServerDaemon>(
                    info.Attributes.GetValueOrDefault("name", ""),
                    Utility.GetColorFromString(info.Attributes.GetValue("color"), Color.White),
                    os,
                    info.Attributes.GetValueOrDefault("foldername", ""),
                    info.Attributes.GetBool("needsAuh")
                    );

                daemon.hasReturnViewButton = info.Attributes.GetBool("hasReturnViewButton");
            });

            executor.AddExecutor("daemons.DHSDaemon", (exec, info) =>
                                 result.AddDaemon <DLCHubServer>("unknown", "unknown", os));

            executor.AddExecutor("daemons.CustomConnectDisplayDaemon", (exec, info) =>
                                 result.AddDaemon <CustomConnectDisplayDaemon>(os));

            executor.AddExecutor("daemons.DatabaseDaemon", (exec, info) =>
            {
                var daemon = new DatabaseDaemon(result,
                                                os,
                                                info.Attributes.GetValueOrDefault("Name", null),
                                                info.Attributes.GetValueOrDefault("Permissions", null),
                                                info.Attributes.GetValueOrDefault("DataType", null),
                                                info.Attributes.GetValueOrDefault("Foldername", null),
                                                Utility.GetColorFromString(info.Attributes.GetValueOrDefault("Color", null), true, null)
                                                );

                result.daemons.Add(daemon);

                var AdminEmailAccount = info.Attributes.GetValue("AdminEmailAccount");

                var adminEmailAccount = info.Attributes.GetValue("AdminEmailAccount");

                if (string.IsNullOrWhiteSpace(adminEmailAccount))
                {
                    return;
                }
                daemon.adminResetPassEmailAccount = adminEmailAccount;
                daemon.adminResetEmailHostID      = info.Attributes.GetValue("AdminEmailHostID");
            });

            executor.AddExecutor("daemons.WhiteListAuthenticatorDaemon", (exec, info) =>
            {
                var daemon = result.AddDaemon <WhitelistConnectionDaemon>(os);
                daemon.AuthenticatesItself = info.Attributes.GetBool("SelfAuthenticating");
            });

            executor.AddExecutor("daemons.IRCDaemon", (exec, info) =>
                                 result.AddDaemon <IRCDaemon>(os, "LOAD ERROR"));


            executor.AddExecutor("daemons.MarkovTextDaemon", (exec, info) =>
                                 result.AddDaemon <MarkovTextDaemon>(
                                     os,
                                     info.Attributes.GetValue("Name"),
                                     info.Attributes.GetValue("SourceFilesContentFolder")
                                     )
                                 );

            executor.AddExecutor("daemons.AircraftDaemon", (exec, info) =>
            {
                var srcVec = Vector2.Zero;
                var dstVec = Vector2.One * 0.5f;
                if (info.Attributes.ContainsKey("OriginX"))
                {
                    srcVec.X = info.Attributes.GetFloat("OriginX");
                }
                if (info.Attributes.ContainsKey("OriginY"))
                {
                    srcVec.Y = info.Attributes.GetFloat("OriginY");
                }

                if (info.Attributes.ContainsKey("DestX"))
                {
                    dstVec.X = info.Attributes.GetFloat("DestX");
                }
                if (info.Attributes.ContainsKey("DestY"))
                {
                    dstVec.Y = info.Attributes.GetFloat("DestY");
                }

                result.AddDaemon <AircraftDaemon>(
                    os,
                    info.Attributes.GetValueOrDefault("Name", "Pacific Charter Flight"),
                    srcVec,
                    dstVec,
                    info.Attributes.GetFloat("Progress", .5f)
                    );
            });

            executor.AddExecutor("daemons.LogoCustomConnectDisplayDaemon", (exec, info) =>
                                 result.AddDaemon <LogoCustomConnectDisplayDaemon>(
                                     os,
                                     info.Attributes.GetValueOrDefault("logo", null),
                                     info.Attributes.GetValueOrDefault("title", null),
                                     info.Attributes.GetBool("overdrawLogo"),
                                     info.Attributes.GetValueOrDefault("buttonAlignment", null)
                                     )
                                 );

            executor.AddExecutor("daemons.LogoDaemon", (exec, info) =>
            {
                var daemon = result.AddDaemon <LogoDaemon>(
                    os,
                    result.name,
                    info.Attributes.GetBool("ShowsTitle", true),
                    info.Attributes.GetValueOrDefault("LogoImagePath", null)
                    );

                daemon.TextColor = Utility.GetColorFromString(info.Attributes.GetValue("TextColor"), Color.White);
            });

            executor.AddExecutor("daemons.DLCCredits", (exec, info) =>
            {
                var overrideButtonText = info.Attributes.GetValueOrDefault("Button", null);
                var overrideTitle      = info.Attributes.GetValueOrDefault("Title", null);
                DLCCreditsDaemon daemon;
                if (overrideButtonText == null && overrideTitle == null)
                {
                    daemon = result.AddDaemon <DLCCreditsDaemon>(os);
                }
                else
                {
                    daemon = result.AddDaemon <DLCCreditsDaemon>(os, overrideTitle, overrideButtonText);
                }
                if (info.Attributes.TryGetValue("Action", out var buttonAction))
                {
                    daemon.ConditionalActionsToLoadOnButtonPress = buttonAction;
                }
            });

            executor.AddExecutor("daemon.FastActionHost", (exec, info) =>
                                 result.AddDaemon <FastActionHost>(os, result.name));

            #endregion

            executor.AddExecutor("filesystem", (exec, info) =>
            {
                var rootInfo = info.Children.FirstOrDefault(e => e.Name == "folder");
                if (rootInfo == null)
                {
                    /* TODO: Error reporting */
                }

                result.files = new FileSystem(true)
                {
                    root = LoadFolder(rootInfo)
                };
            }, true);

            foreach (var exec in ComputerLoaders)
            {
                executor.AddExecutor(exec.Key, exec.Value);
            }

            executor.Execute(root);

            if (compSpec == "mail")
            {
                os.netMap.mailServer = result;
            }
            if (compSpec == "player")
            {
                os.thisComputer = result;
            }
            return(result);
        }
Exemple #5
0
        public static Computer LoadComputer(string filename, OS os, bool preventAddingToNetmap = false, bool preventInitDaemons = false)
        {
            PreventNetmapAdd  = preventAddingToNetmap;
            PreventDaemonInit = preventInitDaemons;

            filename = LocalizedFileLoader.GetLocalizedFilepath(filename);
            Computer result = null;
            string   themeData;

            var executor    = new EventExecutor(filename, ignoreCase: true);
            var readContent = true;

            if (filename.Contains("ExampleComputer.xml") && !Util.Extensions.CheckLabyrinths())
            {
                executor.OnRead += exec =>
                {
                    var val = Regex.Replace(exec.Reader.Value.Trim().ToLower().Replace('_', ' '), @"s/\s{2,}/ /g", "");
                    if (readContent && val == "end labyrinths only content")
                    {
                        readContent = true;
                    }
                    else if (!readContent && val == "start labyrinths only content")
                    {
                        readContent = false;
                    }
                    return(readContent);
                };
            }

            executor.AddExecutor("Computer", (exec, info) =>
            {
                var compType = info.Attributes.GetValue("type");
                result       = new Computer(
                    info.Attributes.GetValue("name", true) ?? "UNKNOWN",
                    info.Attributes.GetValue("ip", true) ?? Utility.GenerateRandomIP(),
                    os.netMap.getRandomPosition(),
                    Convert.ToInt32(info.Attributes.GetValue("security")),
                    compType?.ToLower() == "empty" ? (byte)4 : Convert.ToByte(compType),
                    os)
                {
                    idName = info.Attributes.GetValue("id") ?? "UNKNOWN",
                    AllowsDefaultBootModule = info.Attributes.GetValue("allowsDefaultBootModule")?.ToLower() != "false",
                    icon = info.Attributes.GetValue("icon")
                };
                if (result.type != 4)
                {
                    return;
                }
                var folder = result.files.root.searchForFolder("home");
                folder?.files.Clear();
                folder?.folders.Clear();
            });

            executor.AddExecutor("Computer.File", (exec, info) =>
            {
                var encodedFileStr = info.Attributes.GetValueOrDefault("name", "Data", true).HacknetFilter();
                themeData          = info.Value;
                if (string.IsNullOrEmpty(themeData))
                {
                    themeData = Utility.GenerateBinString();
                }
                themeData          = themeData.HacknetFilter();
                var folderFromPath = result.getFolderFromPath(
                    info.Attributes.GetValueOrDefault("path", "home"), true);
                if (!info.Attributes.GetBool("EduSafe", true) &&
                    (Settings.EducationSafeBuild || !Settings.EducationSafeBuild) &&
                    info.Attributes.GetBool("EduSafeOnly"))
                {
                    return;
                }
                var file = folderFromPath.searchForFile(encodedFileStr);
                if (file == null)
                {
                    folderFromPath.files.Add(new FileEntry(themeData, encodedFileStr));
                }
                else
                {
                    file.data = encodedFileStr;
                }
            }, true);

            executor.AddExecutor("Computer.EncryptedFile", (exec, info) =>
            {
                var encodedFileStr = info.Attributes.GetValueOrDefault("name", "Data", true);
                var header         = info.Attributes.GetValueOrDefault("header", "ERROR");
                var ip             = info.Attributes.GetValueOrDefault("ip", "ERROR");
                var pass           = info.Attributes.GetValueOrDefault("pass", "");
                var extension      = info.Attributes.GetValue("extension");
                var doubleAttr     = info.Attributes.GetBool("double");
                themeData          = info.Value;
                if (string.IsNullOrEmpty(themeData))
                {
                    themeData = Utility.GenerateBinString();
                }
                themeData = themeData.HacknetFilter();
                if (doubleAttr)
                {
                    themeData = FileEncrypter.EncryptString(themeData, header, ip, pass, extension);
                }
                themeData = FileEncrypter.EncryptString(themeData, header, ip, pass,
                                                        (doubleAttr ? "_LAYER2.dec" : extension));
                var folderFromPath = result.getFolderFromPath(
                    info.Attributes.GetValue("path") ?? "home", true);
                var file = folderFromPath.searchForFile(encodedFileStr);
                if (file == null)
                {
                    folderFromPath.files.Add(new FileEntry(themeData, encodedFileStr));
                }
                else
                {
                    file.data = themeData;
                }
            }, true);


            executor.AddExecutor("Computer.MemoryDumpFile", (exec, info) =>
            {
                var memoryInfo = info.Children.FirstOrDefault(e => e.Name == "Memory");
                if (memoryInfo == null)
                {
                    /* TODO: error reporting */
                }
                var memoryContents = ReplacementsCommon.LoadMemoryContents(memoryInfo);
                var fileName       = info.Attributes.GetValueOrDefault("name", "Data");
                var folderFromPath = result.getFolderFromPath(info.Attributes.GetValueOrDefault("path", "home"), true);
                var file           = folderFromPath.searchForFile(fileName);
                if (file != null)
                {
                    file.data = memoryContents.GetEncodedFileString();
                }
                else
                {
                    folderFromPath.files.Add(new FileEntry(memoryContents.GetEncodedFileString(), fileName));
                }
            }, true);

            executor.AddExecutor("Computer.Memory", (exec, info) =>
            {
                result.Memory = ReplacementsCommon.LoadMemoryContents(info);
            }, true);

            executor.AddExecutor("Computer.CustomThemeFile", (exec, info) =>
            {
                var encodedFileStr = info.Attributes.GetValueOrDefault("name", "Data", true);
                themeData          = ThemeManager.getThemeDataStringForCustomTheme(info.Attributes.GetValue("themePath"));
                themeData          = string.IsNullOrEmpty(themeData)
                    ? "DEFINITION ERROR - Theme generated incorrectly. No Custom theme found at definition path"
                    : themeData.HacknetFilter();
                var folderFromPath = result.getFolderFromPath(
                    info.Attributes.GetValueOrDefault("path", "home"), true);
                var file = folderFromPath.searchForFile(encodedFileStr);
                if (file == null)
                {
                    folderFromPath.files.Add(new FileEntry(themeData, encodedFileStr));
                }
                else
                {
                    file.data = themeData;
                }
            });

            executor.AddExecutor("Computer.Ports", (exec, info) =>
                                 ComputerLoader.loadPortsIntoComputer(info.Value, result), true);

            executor.AddExecutor("Computer.PositionNear", (exec, info) =>
            {
                var target        = info.Attributes.GetValueOrDefault("target", "");
                var position      = info.Attributes.GetInt("position", 1);
                var total         = info.Attributes.GetInt("total", 3);
                var force         = info.Attributes.GetBool("force");
                var extraDistance = MathHelper.Clamp(info.Attributes.GetFloat("extraDistance"), -1, 1);
                ComputerLoader.postAllLoadedActions += () =>
                {
                    var c = Programs.getComputer(os, target);
                    if (c != null)
                    {
                        result.location = c.location
                                          + Corporation.getNearbyNodeOffset(
                            c.location,
                            position,
                            total,
                            os.netMap,
                            extraDistance,
                            force);
                    }
                };
            });

            executor.AddExecutor("Computer.Proxy", (exec, info) =>
            {
                var time = info.Attributes.GetFloat("time", 1);
                if (time <= 0f)
                {
                    result.hasProxy    = false;
                    result.proxyActive = false;
                }
            });

            executor.AddExecutor("Computer.PortsForCrack", (exec, info) =>
            {
                var val = info.Attributes.GetInt("val", -1);
                if (val != -1)
                {
                    result.portsNeededForCrack = val - 1;
                }
            });

            executor.AddExecutor("Computer.Firewall", (exec, info) =>
            {
                var level = info.Attributes.GetInt("level", 1);
                if (level <= 0)
                {
                    result.firewall = null;
                }
                else
                {
                    var solution = info.Attributes.GetValue("solution");
                    if (solution == null)
                    {
                        result.addFirewall(level);
                    }
                    else
                    {
                        result.addFirewall(
                            level, solution, info.Attributes.GetFloat("additionalTime"));
                    }
                }
            });

            executor.AddExecutor("Computer.Link", (exec, info) =>
            {
                var linkedComp =
                    Programs.getComputer(os, info.Attributes.GetValueOrDefault("target", ""));
                if (linkedComp != null)
                {
                    result.links.Add(os.netMap.nodes.IndexOf(linkedComp));
                }
            });

            executor.AddExecutor("Computer.Dlink", (exec, info) =>
            {
                /* captures for lambda */
                var offsetComp = result;
                var linkTo     = info.Attributes.GetValueOrDefault("target", "");
                ComputerLoader.postAllLoadedActions += () =>
                {
                    var linkedComp =
                        Programs.getComputer(os, linkTo);
                    if (linkedComp != null)
                    {
                        offsetComp.links.Add(os.netMap.nodes.IndexOf(linkedComp));
                    }
                };
            });

            executor.AddExecutor("Computer.Trace", (exec, info) =>
                                 result.traceTime = info.Attributes.GetFloat("time", 1));

            executor.AddExecutor("Computer.AdminPass", (exec, info) =>
                                 result.setAdminPassword(
                                     info.Attributes.GetValue("pass", true) ?? PortExploits.getRandomPassword()));

            executor.AddExecutor("Computer.Admin", (exec, info) =>
                                 result.admin = Utility.GetAdminFromString(
                                     info.Attributes.GetValueOrDefault("type", "basic"),
                                     info.Attributes.GetBool("resetPassword", true),
                                     info.Attributes.GetBool("isSuper")
                                     ));

            executor.AddExecutor("Computer.PortRemap", (exec, info) =>
            {
                if (!string.IsNullOrWhiteSpace(info.Value))
                {
                    result.PortRemapping = PortRemappingSerializer.Deserialize(info.Value);
                }
            }, true);

            executor.AddExecutor("Computer.ExternalCounterpart", (exec, info)
                                 => result.externalCounterpart = new ExternalCounterpart(info.Attributes.GetValue("name"),
                                                                                         ExternalCounterpart.getIPForServerName(info.Attributes.GetValue("id"))));

            executor.AddExecutor("Computer.Account", (exec, info) =>
            {
                byte type      = 0;
                string typeStr = info.Attributes.GetValueOrDefault("type", "admin").ToLower(),
                password       = info.Attributes.GetValueOrDefault("password", "ERROR", true),
                username       = info.Attributes.GetValueOrDefault("username", "ERROR", true);
                switch (typeStr)
                {
                case "admin": type = 0; break;

                case "all": type = 1; break;

                case "mail": type = 2; break;

                case "missionlist": type = 3; break;

                default:
                    if (char.IsDigit(typeStr[0]))
                    {
                        byte.TryParse(typeStr, out type);
                    }
                    break;
                }
                var addUser = true;
                for (int i = 0; i < result.users.Count; i++)
                {
                    var userDetail = result.users[i];
                    if (userDetail.name == username)
                    {
                        userDetail.pass = password;
                        userDetail.type = type;
                        result.users[i] = userDetail;
                        if (username == "admin")
                        {
                            result.adminPass = password;
                        }
                        addUser = false;
                    }
                }
                if (addUser)
                {
                    result.AddUserDetail(username, password, type);
                }
            });

            executor.AddExecutor("Computer.Tracker", (exec, info) => result.HasTracker = true);

            executor.AddExecutor("Computer.MissionListingServer", (exec, info) =>
            {
                result.AddDaemon <MissionListingServer>(
                    info.Attributes.GetValueOrDefault("name", "ERROR", true),
                    info.Attributes.GetValueOrDefault("group", "ERROR", true),
                    os,
                    info.Attributes.GetBool("public"),
                    info.Attributes.GetBool("assigner"));
            });

            executor.AddExecutor("Computer.VariableMissionListingServer", (exec, info) =>
            {
                var title = info.Attributes.GetValue("title", true);
                var missionListingServer = result.AddDaemon <MissionListingServer>(
                    info.Attributes.GetValue("name", true),
                    info.Attributes.GetValue("iconPath"),
                    info.Attributes.GetValue("articleFolderPath"),
                    Utility.GetColorFromString(info.Attributes.GetValue("color"), Color.IndianRed),
                    os,
                    info.Attributes.GetBool("public"),
                    info.Attributes.GetBool("assigner")
                    );
                if (title != null)
                {
                    missionListingServer.listingTitle = title;
                }
            });

            executor.AddExecutor("Computer.MissionHubServer", (exec, info) =>
            {
                var missionPath = info.Attributes.GetValueOrDefault("missionFolderPath", "").Replace('\\', '/');
                if (!missionPath.EndsWith("/", StringComparison.InvariantCulture))
                {
                    missionPath += "/";
                }
                var hubServer = result.AddDaemon <MissionHubServer>(
                    info.Attributes.GetValue("serviceName"),
                    info.Attributes.GetValueOrDefault("groupName", "", true),
                    os
                    );
                hubServer.MissionSourceFolderPath =
                    (Settings.IsInExtensionMode
                        ? ExtensionLoader.ActiveExtensionInfo.FolderPath + "/"
                        : "Content/Missions/") + missionPath;
                hubServer.themeColor           = info.Attributes.GetColor("themeColor", Color.PaleTurquoise);
                hubServer.themeColorBackground = info.Attributes.GetColor("backgroundColor", Color.PaleTurquoise);
                hubServer.themeColorLine       = info.Attributes.GetColor("line Color", Color.PaleTurquoise);
                hubServer.allowAbandon         = info.Attributes.GetBool("allowAbandon", true);
            });

            executor.AddExecutor("Computer.MailServer", (exec, info) =>
            {
                var mailServer = result.AddDaemon <MailServer>(
                    info.Attributes.GetValueOrDefault("name", "Mail Server"),
                    os);
                mailServer.shouldGenerateJunkEmails = info.Attributes.GetBool("generateJunk", true);
                var color = info.Attributes.GetColor("color", true);
                if (color.HasValue)
                {
                    mailServer.setThemeColor(color.Value);
                }
                foreach (var emailInfo in info.Children.Where((i) => i.Name.ToLower() == "email"))
                {
                    mailServer.AddEmailToServer(
                        emailInfo.Attributes.GetValue("sender"),
                        emailInfo.Attributes.GetValue("recipient"),
                        emailInfo.Attributes.GetValue("subject"),
                        emailInfo.Value
                        );
                }
            }, true);

            executor.AddExecutor("Computer.AddEmailDaemon", (exec, info)
                                 => result.AddDaemon <AddEmailDaemon>("Final Task", os));

            executor.AddExecutor("Computer.DeathRowDatabase", (exec, info)
                                 => result.AddDaemon <DeathRowDatabaseDaemon>("Death Row Database", os));

            executor.AddExecutor("Computer.AcademicDatabase", (exec, info)
                                 => result.AddDaemon <AcademicDatabaseDaemon>("International Academic Database", os));

            executor.AddExecutor("Computer.IspSystem", (exec, info)
                                 => result.AddDaemon <ISPDaemon>(os));

            executor.AddExecutor("Computer.MessageBoard", (exec, info) =>
            {
                var messageBoardDaemon       = result.AddDaemon <MessageBoardDaemon>(os);
                messageBoardDaemon.name      = info.Attributes.GetValueOrDefault("name", "Anonymous");
                messageBoardDaemon.BoardName = messageBoardDaemon.name;
                const string content         = "Content/Missions/";
                foreach (var threadInfo in info.Children.Where((cinfo) => cinfo.Name.ToLower() == "thread"))
                {
                    var threadLoc = threadInfo.Value ?? "UNKNOWN";
                    if (threadLoc.StartsWith(content, StringComparison.InvariantCulture))
                    {
                        threadLoc = threadLoc.Substring(content.Length);
                    }
                    messageBoardDaemon.AddThread(Utils.readEntireFile(
                                                     (Settings.IsInExtensionMode ?
                                                      ExtensionLoader.ActiveExtensionInfo.FolderPath + "/" :
                                                      content
                                                     ) + threadLoc
                                                     ));
                }
            }, true);

            executor.AddExecutor("Computer.AddAvconDemoEndDaemon", (exec, info)
                                 => result.AddDaemon <AvconDemoEndDaemon>("Demo End", os));

            executor.AddExecutor("Computer.AddWebServer", (exec, info) =>
                                 result.AddDaemon <WebServerDaemon>(
                                     info.Attributes.GetValueOrDefault("name", "Web Server"),
                                     os,
                                     info.Attributes.GetValue("url")
                                     ).registerAsDefaultBootDaemon());

            executor.AddExecutor("Computer.AddOnlineWebServer", (exec, info) =>
            {
                var webOnlineServerDaemon = result.AddDaemon <OnlineWebServerDaemon>(
                    info.Attributes.GetValueOrDefault("name", "Web Server"),
                    os);
                webOnlineServerDaemon.setURL(
                    info.Attributes.GetValueOrDefault("url", webOnlineServerDaemon.webURL));
                webOnlineServerDaemon.registerAsDefaultBootDaemon();
            });


            executor.AddExecutor("Computer.UploadServerDaemon", (exec, info) =>
            {
                var uploadServerDaemon = result.AddDaemon <UploadServerDaemon>(
                    info.Attributes.GetValueOrDefault("name", "File Upload Server"),
                    info.Attributes.GetColor("color", new Color(0, 94, 38)),
                    os,
                    info.Attributes.GetValue("folder"),
                    info.Attributes.GetBool("needsAuth")
                    );
                uploadServerDaemon.hasReturnViewButton = info.Attributes.GetBool("hasReturnViewButton");
                uploadServerDaemon.registerAsDefaultBootDaemon();
            });

            executor.AddExecutor("Computer.MedicalDatabase", (exec, info)
                                 => result.AddDaemon <MedicalDatabaseDaemon>(os));

            executor.AddExecutor("Computer.HeartMonitor", (exec, info)
                                 => result.AddDaemon <HeartMonitorDaemon>(os)
                                 .PatientID = info.Attributes.GetValueOrDefault("patient", "UNKNOWN"));

            executor.AddExecutor("Computer.PointClicker", (exec, info)
                                 => result.AddDaemon <PointClickerDaemon>("Point Clicker!", os));

            executor.AddExecutor("Computer.PorthackHeart", (exec, info)
                                 => result.AddDaemon <PorthackHeartDaemon>(os));

            executor.AddExecutor("Computer.SongChangerDaemon", (exec, info)
                                 => result.AddDaemon <SongChangerDaemon>(os));

            executor.AddExecutor("Computer.CustomConnectDisplayDaemon", (exec, info)
                                 => result.AddDaemon <CustomConnectDisplayDaemon>(os));

            executor.AddExecutor("Computer.DatabaseDaemon", (exec, info) =>
            {
                info.Name.ThrowNoLabyrinths();
                var emailAccount = info.Attributes.GetValue("AdminEmailAccount");

                var databaseColor = info.Attributes.GetColor("Color", true);
                if (!databaseColor.HasValue)
                {
                    databaseColor = os.highlightColor;
                }

                var databaseDaemon = result.AddDaemon <DatabaseDaemon>(
                    os,
                    info.Attributes.GetValueOrDefault("Name", "Database"),
                    DatabaseDaemon.GetDatabasePermissionsFromString(
                        info.Attributes.GetValueOrDefault("Permissions", "")
                        ),
                    info.Attributes.GetValue("DataType"),
                    info.Attributes.GetValueOrDefault("Foldername", "Database"),
                    databaseColor);
                if (!string.IsNullOrWhiteSpace(emailAccount))
                {
                    databaseDaemon.adminResetEmailHostID      = info.Attributes.GetValue("AdminEmailHostID");
                    databaseDaemon.adminResetPassEmailAccount = emailAccount;
                }
                if (info.Children.Count > 0)
                {
                    var dataset = databaseDaemon.GetDataset();
                    foreach (var e in info.Children)
                    {
                        if (e.Name == databaseDaemon.DataTypeIdentifier)
                        {
                            dataset.Add(new DatabaseDaemonHandler.DataInfo(e));
                        }
                    }
                }
            }, true);



            executor.AddExecutor("Computer.WhitelistAuthenticatorDaemon", (exec, info)
                                 => result.AddDaemon(
                                     new WhitelistConnectionDaemon(result, os)
            {
                RemoteSourceIP      = info.Attributes.GetValue("Remote"),
                AuthenticatesItself = info.Attributes.GetBool("SelfAuthenticating", true)
            }));


            executor.AddExecutor("Computer.MarkovTextDaemon", (exec, info)
                                 => result.AddDaemon <MarkovTextDaemon>(
                                     os,
                                     info.Attributes.GetValue("Name"),
                                     info.Attributes.GetValue("SourceFilesContentFolder")
                                     ));

            executor.AddExecutor("Computer.IrcDaemon", (exec, info) =>
            {
                var rCDaemon = result.AddDaemon <IRCDaemon>(
                    os,
                    info.Attributes.GetValueOrDefault("Remote", "IRC Server")
                    );
                rCDaemon.ThemeColor    = info.Attributes.GetColor("themeColor", new Color(184, 2, 141));
                rCDaemon.RequiresLogin = info.Attributes.GetBool("needsLogin");
                foreach (var cinfo in info.Children)
                {
                    switch (cinfo.Name.ToLower())
                    {
                    case "user":
                    case "agent":
                        var name = cinfo.Attributes.GetValue("name", true);
                        if (!string.IsNullOrWhiteSpace(name))
                        {
                            rCDaemon.UserColors.Add(name,
                                                    cinfo.Attributes.GetColor("color", Color.LightGreen));
                        }

                        break;

                    case "post":
                        var user = cinfo.Attributes.GetValue("user", true);
                        if (!string.IsNullOrWhiteSpace(user))
                        {
                            rCDaemon.StartingMessages.Add(
                                new KeyValuePair <string, string>(user, cinfo.Value?.HacknetFilter()));
                        }

                        break;
                    }
                }
            }, true);

            executor.AddExecutor("Computer.AircraftDaemon", (exec, info) =>
            {
                info.Name.ThrowNoLabyrinths();
                result.AddDaemon <AircraftDaemon>(
                    os,
                    info.Attributes.GetValue("Name"),
                    info.Attributes.GetVector2(defaultVal: Vector2.Zero),
                    info.Attributes.GetVector2("Dest", defaultVal: Vector2.One * 0.5f),
                    info.Attributes.GetFloat("Progress", 0.5f)
                    );
            });

            executor.AddExecutor("Computer.LogoCustomConnectDisplayDaemon", (exec, info)
                                 => result.AddDaemon <LogoCustomConnectDisplayDaemon>(
                                     os,
                                     info.Attributes.GetValue("logo"),
                                     info.Attributes.GetValue("title", true),
                                     info.Attributes.GetBool("overdrawLogo"),
                                     info.Attributes.GetValue("buttonAlignment")
                                     ));

            executor.AddExecutor("Computer.LogoDaemon", (exec, info)
                                 => result.AddDaemon(
                                     new LogoDaemon(
                                         result,
                                         os,
                                         result.name,
                                         info.Attributes.GetBool("ShowsTitle", true),
                                         info.Attributes.GetValue("LogoImagePath"))
            {
                TextColor = info.Attributes.GetColor("TextColor", Color.White),
                BodyText  = info.Value
            }
                                     ), true);

            executor.AddExecutor("Computer.DHSDaemon", (exec, info) =>
            {
                info.Name.ThrowNoLabyrinths();

                var groupName             = info.Attributes.GetValueOrDefault("groupName", "UNKNOWN");
                var addsFactionPoint      = info.Attributes.GetBool("addsFactionPointOnMissionComplete", true);
                var autoClearMissions     = info.Attributes.GetBool("autoClearMissionsOnPlayerComplete", true);
                var allowContractAbbandon = info.Attributes.GetBool("allowContractAbbandon");
                var themeColor            = info.Attributes.GetColor("themeColor", new Color(38, 201, 155));

                var dlcHubServer = result.AddDaemon <DLCHubServer>("DHS", groupName, os);
                dlcHubServer.AddsFactionPointForMissionCompleteion = addsFactionPoint;
                dlcHubServer.AutoClearMissionsOnSingleComplete     = autoClearMissions;
                dlcHubServer.AllowContractAbbandon = allowContractAbbandon;
                dlcHubServer.themeColor            = themeColor;

                foreach (var cinfo in info.Children.Where(v =>
                                                          v.Name.ToLower() == "user" || v.Name.ToLower() == "agent")
                         )
                {
                    var name     = cinfo.Attributes.GetValue("name", true);
                    var password = cinfo.Attributes.GetValueOrDefault("pass", "password");
                    var color    = cinfo.Attributes.GetColor("color", Color.LightGreen);
                    if (!string.IsNullOrWhiteSpace(name))
                    {
                        dlcHubServer.AddAgent(name, password, color);
                    }
                }
            }, true);

            void creditFunc(IExecutor exec, ElementInfo info)
            {
                var inputArr = new List <object>
                {
                    os,
                    info.Attributes.GetValue("Title", true),
                    info.Attributes.GetValue("ButtonText", true)
                }.Where((i) => i != null).ToArray();

                result.AddDaemon <DLCCreditsDaemon>(inputArr.ToArray())
                .ConditionalActionsToLoadOnButtonPress =
                    info.Attributes.GetValue("ConditionalActionSetToRunOnButtonPressPath");
            }

            executor.AddExecutor("Computer.DLCCredits", creditFunc);
            executor.AddExecutor("Computer.CreditsDaemon", creditFunc);

            executor.AddExecutor("Computer.FastActionHost", (exec, info)
                                 => result.AddDaemon <FastActionHost>(os, result.name));

            executor.AddExecutor("Computer.eosDevice", (exec, info)
                                 => AddEosComputer(info, result, os), true);

            HandlerListener.DaemonLoadListener(result, executor);

            foreach (var exec in ComputerLoaders)
            {
                executor.AddExecutor(exec.Key, exec.Value);
            }

            executor.OnOpenFile                   += OnOpenFile;
            executor.OnRead                       += OnRead;
            executor.OnReadElement                += OnReadElement;
            executor.OnReadEndElement             += OnReadEndElement;
            executor.OnReadDocument               += OnReadDocument;
            executor.OnReadComment                += OnReadComment;
            executor.OnReadText                   += OnReadText;
            executor.OnReadProcessingInstructions += OnReadProcessingInstructions;
            executor.OnCloseFile                  += OnCloseFile;

            executor.OnCloseFile += reader =>
            {
                if (!preventInitDaemons)
                {
                    result.initDaemons();
                }
                if (!preventAddingToNetmap)
                {
                    os.netMap.nodes.Add(result);
                }
            };

            executor.Parse();
            return(result);
        }
        public static Computer LoadComputer(ElementInfo info, OS os)
        {
            var name = info.Attributes.GetString("name");
            var ip   = info.Attributes.GetString("ip");
            var type = info.Attributes.GetByte("type");
            var spec = info.Attributes.GetString("spec");

            var location = info.Children.GetElement("location");

            var security = info.Children.GetElement("security");
            var level    = security.Attributes.GetInt("level");

            Firewall firewall = null;

            if (info.Children.TryGetElement("firewall", out var firewallInfo))
            {
                firewall = new Firewall(
                    firewallInfo.Attributes.GetInt("complexity"),
                    firewallInfo.Attributes.GetString("solution", null),
                    firewallInfo.Attributes.GetFloat("additionalDelay")
                    );
            }

            ReplacementsCommon.isPathfinderComputer = true;
            var comp = new Computer(name, ip, location.Attributes.GetVector("x", "y", Vector2.Zero).Value, level, type, os)
            {
                idName             = info.Attributes.GetString("id"),
                attatchedDeviceIDs = info.Attributes.GetString("devices", null),
                icon                = info.Attributes.GetString("icon", null),
                HasTracker          = info.Attributes.GetBool("tracker"),
                firewall            = firewall,
                traceTime           = security.Attributes.GetFloat("traceTime"),
                portsNeededForCrack = security.Attributes.GetInt("portsToCrack"),
                adminIP             = security.Attributes.GetString("adminIP")
            };

            ReplacementsCommon.isPathfinderComputer = false;

            var proxyTime = security.Attributes.GetFloat("proxyTime");

            if (proxyTime > 0)
            {
                comp.addProxy(proxyTime);
            }
            else
            {
                comp.hasProxy    = false;
                comp.proxyActive = false;
            }

            if (info.Children.TryGetElement("admin", out var adminInfo))
            {
                Administrator.AdministratorManager.LoadAdministrator(adminInfo, comp, os);
            }

            foreach (var link in info.Children.GetElement("links").Content?
                     .Split((char[])null, StringSplitOptions.RemoveEmptyEntries) ?? new string[0])
            {
                comp.links.Add(int.Parse(link));
            }

            if (info.Children.TryGetElement("portsOpen", out var portsOpen))
            {
                PortManager.LoadPortsFromStringVanilla(comp, portsOpen.Content);
            }

            if (info.Children.TryGetElement("portRemap", out var remap))
            {
                PortManager.LoadPortRemapsFromStringVanilla(comp, remap.Content);
            }

            if (info.Children.TryGetElement("ports", out var ports))
            {
                if (ports.Content != null)
                {
                    foreach (var port in ports.Content.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        var parts       = port.Split(':');
                        var record      = PortManager.GetPortRecordFromProtocol(parts[0]);
                        var displayName = parts[3].Replace('_', ' ');
                        var portNum     = int.Parse(parts[2]);
                        if (record == null)
                        {
                            PortManager.RegisterPort(record = new PortRecord(
                                                         parts[0],
                                                         displayName,
                                                         portNum,
                                                         int.Parse(parts[1])
                                                         ));
                        }

                        comp.AddPort(record.CreateState(
                                         comp,
                                         displayName,
                                         portNum
                                         ));
                    }
                }

                foreach (var port in ports.Children)
                {
                    var record      = PortManager.GetPortRecordFromProtocol(port.Name);
                    var displayName = port.Children.GetElement("Display").Content;
                    var portNum     = int.Parse(port.Children.GetElement("Number").Content);
                    if (record == null)
                    {
                        PortManager.RegisterPort(record = new PortRecord(
                                                     port.Name,
                                                     displayName,
                                                     portNum,
                                                     int.Parse(port.Children.GetElement("Original").Content)
                                                     ));
                    }
                    comp.AddPort(record.CreateState(
                                     comp,
                                     displayName,
                                     portNum
                                     ));
                }
            }

            comp.users.Clear();
            if (info.Children.TryGetElement("users", out var users))
            {
                foreach (var user in users.Children.Where(x => x.Name == "user"))
                {
                    var username = user.Attributes.GetString("name");
                    var pass     = user.Attributes.GetString("pass");

                    var userDetail = new UserDetail(
                        username,
                        pass,
                        user.Attributes.GetByte("type")
                        )
                    {
                        known = user.Attributes.GetBool("known")
                    };

                    if (username.ToLower() == "admin")
                    {
                        comp.adminPass = pass;
                    }

                    comp.users.Add(userDetail);
                }
            }

            if (info.Children.TryGetElement("Memory", out var memory))
            {
                comp.Memory = ReplacementsCommon.LoadMemoryContents(memory);
            }

            #region Daemons

            if (info.Children.TryGetElement("daemons", out var daemons))
            {
                foreach (var daemon in daemons.Children)
                {
                    if (Daemon.DaemonManager.TryLoadCustomDaemon(daemon, comp, os))
                    {
                        continue;
                    }

                    switch (daemon.Name)
                    {
                    case "MailServer":
                        var mailserver = new MailServer(comp, daemon.Attributes.GetString("name"), os);
                        if (daemon.Attributes.TryGetValue("color", out var mail_color))
                        {
                            mailserver.setThemeColor(Utils.convertStringToColor(mail_color));
                        }

                        comp.daemons.Add(mailserver);
                        break;

                    case "MissionListingServer":
                        var listing_name       = daemon.Attributes.GetString("name");
                        var listing_group      = daemon.Attributes.GetString("group");
                        var listing_isPublic   = daemon.Attributes.GetBool("public");
                        var listing_isAssigner = daemon.Attributes.GetBool("assign");
                        var listing_articles   = daemon.Attributes.GetString("articles");

                        MissionListingServer listingserver;
                        if (daemon.Attributes.TryGetValue("icon", out var listing_icon) &&
                            daemon.Attributes.TryGetValue("color", out var listing_color))
                        {
                            listingserver = new MissionListingServer(comp, listing_name, listing_icon,
                                                                     listing_articles,
                                                                     Utils.convertStringToColor(listing_color), os, listing_isPublic,
                                                                     listing_isAssigner);
                        }
                        else
                        {
                            listingserver = new MissionListingServer(comp, name, listing_group, os,
                                                                     listing_isPublic, listing_isAssigner);
                        }

                        comp.daemons.Add(listingserver);
                        break;

                    case "AddEmailServer":
                        comp.daemons.Add(new AddEmailDaemon(comp, daemon.Attributes.GetString("name"), os));
                        break;

                    case "MessageBoard":
                        var messageboard = new MessageBoardDaemon(comp, os);
                        messageboard.name      = daemon.Attributes.GetString("name");
                        messageboard.BoardName =
                            daemon.Attributes.GetString("boardName", messageboard.BoardName);
                        comp.daemons.Add(messageboard);
                        break;

                    case "WebServer":
                        comp.daemons.Add(new WebServerDaemon(
                                             comp,
                                             daemon.Attributes.GetString("name"),
                                             os,
                                             daemon.Attributes.GetString("url")
                                             ));
                        break;

                    case "OnlineWebServer":
                        var onlinewebserver =
                            new OnlineWebServerDaemon(comp, daemon.Attributes.GetString("name"), os);
                        onlinewebserver.setURL(daemon.Attributes.GetString("url"));
                        comp.daemons.Add(onlinewebserver);
                        break;

                    case "AcademicDatabse":
                        comp.daemons.Add(new AcademicDatabaseDaemon(
                                             comp,
                                             daemon.Attributes.GetString("name"),
                                             os
                                             ));
                        break;

                    case "MissionHubServer":
                        comp.daemons.Add(new MissionHubServer(comp, "unknown", "unknown", os));
                        break;

                    case "DeathRowDatabase":
                        comp.daemons.Add(new DeathRowDatabaseDaemon(comp, "Death Row Database", os));
                        break;

                    case "MedicalDatabase":
                        comp.daemons.Add(new MedicalDatabaseDaemon(comp, os));
                        break;

                    case "HeartMonitor":
                        var heartmon = new HeartMonitorDaemon(comp, os);
                        heartmon.PatientID = daemon.Attributes.GetString("patient", "UNKNOWN");
                        comp.daemons.Add(heartmon);
                        break;

                    case "PointClicker":
                        comp.daemons.Add(new PointClickerDaemon(comp, "Point Clicker!", os));
                        break;

                    case "ispSystem":
                        comp.daemons.Add(new ISPDaemon(comp, os));
                        break;

                    case "porthackheart":
                        comp.daemons.Add(new PorthackHeartDaemon(comp, os));
                        break;

                    case "SongChangerDaemon":
                        comp.daemons.Add(new SongChangerDaemon(comp, os));
                        break;

                    case "UploadServerDaemon":
                        var uploadserver = new UploadServerDaemon(
                            comp,
                            daemon.Attributes.GetString("name"),
                            daemon.Attributes.GetColor("color", Color.White).Value,
                            os,
                            daemon.Attributes.GetString("foldername"),
                            daemon.Attributes.GetBool("needsAuh")
                            );
                        uploadserver.hasReturnViewButton = daemon.Attributes.GetBool("hasReturnViewButton");
                        comp.daemons.Add(uploadserver);
                        break;

                    case "DHSDaemon":
                        comp.daemons.Add(new DLCHubServer(comp, "unknown", "unknown", os));
                        break;

                    case "CustomConnectDisplayDaemon":
                        comp.daemons.Add(new CustomConnectDisplayDaemon(comp, os));
                        break;

                    case "DatabaseDaemon":
                        var databaseserver = new DatabaseDaemon(
                            comp,
                            os,
                            daemon.Attributes.GetString("Name", null),
                            daemon.Attributes.GetString("Permissions"),
                            daemon.Attributes.GetString("DataType"),
                            daemon.Attributes.GetString("Foldername"),
                            daemon.Attributes.GetColor("Color")
                            );
                        databaseserver.adminResetEmailHostID      = daemon.Attributes.GetString("AdminEmailHostID", null);
                        databaseserver.adminResetPassEmailAccount = daemon.Attributes.GetString("AdminEmailAccount", null);
                        comp.daemons.Add(databaseserver);
                        break;

                    case "WhitelistAuthenticatorDaemon":
                        var whitelistserver = new WhitelistConnectionDaemon(comp, os);
                        whitelistserver.AuthenticatesItself = daemon.Attributes.GetBool("SelfAuthenticating", true);
                        comp.daemons.Add(whitelistserver);
                        break;

                    case "IRCDaemon":
                        comp.daemons.Add(new IRCDaemon(comp, os, "LOAD ERROR"));
                        break;

                    case "MarkovTextDaemon":
                        comp.daemons.Add(new MarkovTextDaemon(
                                             comp,
                                             os,
                                             daemon.Attributes.GetString("Name", null),
                                             daemon.Attributes.GetString("SourceFilesContentFolder", null)
                                             ));
                        break;

                    case "AircraftDaemon":
                        comp.daemons.Add(new AircraftDaemon(
                                             comp,
                                             os,
                                             daemon.Attributes.GetString("Name", "Pacific Charter Flight"),
                                             daemon.Attributes.GetVector("OriginX", "OriginY", Vector2.Zero).Value,
                                             daemon.Attributes.GetVector("DestX", "DestY", Vector2.One * 0.5f).Value,
                                             daemon.Attributes.GetFloat("Progress")
                                             ));
                        break;

                    case "LogoCustomConnectDisplayDaemon":
                        comp.daemons.Add(new LogoCustomConnectDisplayDaemon(
                                             comp,
                                             os,
                                             daemon.Attributes.GetString("logo", null),
                                             daemon.Attributes.GetString("title", null),
                                             daemon.Attributes.GetBool("overdrawLogo"),
                                             daemon.Attributes.GetString("buttonAlignment", null)
                                             ));
                        break;

                    case "LogoDaemon":
                        comp.daemons.Add(new LogoDaemon(
                                             comp,
                                             os,
                                             name,
                                             daemon.Attributes.GetBool("ShowsTitle", true),
                                             daemon.Attributes.GetString("LogoImagePath")
                                             )
                        {
                            TextColor = daemon.Attributes.GetColor("TextColor", Color.White).Value
                        });
                        break;

                    case "DLCCredits":
                        DLCCreditsDaemon dlcdaemon = null;
                        string           credits_title, credits_button = null;
                        if (daemon.Attributes.TryGetValue("Title", out credits_title) ||
                            daemon.Attributes.TryGetValue("Button", out credits_button))
                        {
                            dlcdaemon = new DLCCreditsDaemon(comp, os, credits_title, credits_button);
                        }
                        else
                        {
                            dlcdaemon = new DLCCreditsDaemon(comp, os);
                        }
                        dlcdaemon.ConditionalActionsToLoadOnButtonPress = daemon.Attributes.GetString("Action", null);
                        comp.daemons.Add(dlcdaemon);
                        break;

                    case "FastActionHost":
                        comp.daemons.Add(new FastActionHost(comp, os, name));
                        break;
                    }
                }
            }

            #endregion

            comp.files = new FileSystem(true)
            {
                root = LoadFolder(info.Children.GetElement("filesystem").Children.GetElement("folder"))
            };

            switch (spec)
            {
            case "player":
                os.thisComputer = comp;
                break;

            case "mail":
                os.netMap.mailServer = comp;
                break;
            }

            if (EventManager <SaveComputerLoadedEvent> .InvokeAll(new SaveComputerLoadedEvent(os, comp, info)).Cancelled)
            {
                return(null);
            }

            ComputerLookup.Add(comp);
            return(comp);
        }
        static ContentLoader()
        {
            EventManager.onPluginUnload += OnPluginUnload;

            executor.RegisterExecutor("Computer", (exec, info) =>
            {
                var typeString = info.Attributes.GetString("type", "1");
                byte type;
                if (!byte.TryParse(typeString, out type))
                {
                    if (typeString.ToLowerInvariant() == "empty")
                    {
                        type = 4;
                    }
                    else
                    {
                        throw new FormatException("Invalid computer type");
                    }
                }

                comp = new Computer(
                    info.Attributes.GetString("name", "UNKNOWN").Filter(),
                    info.Attributes.GetString("ip", NetworkMap.generateRandomIP()).Filter(),
                    os.netMap.getRandomPosition(),
                    info.Attributes.GetInt("security"),
                    type,
                    os
                    )
                {
                    idName = info.Attributes.GetString("id", "UNKNOWN").Filter(),
                    AllowsDefaultBootModule = info.Attributes.GetBool("allowsDefaultBootModule", true),
                    icon = info.Attributes.GetString("icon", null)
                };
                holder.Comp = comp;

                if (type == 4)
                {
                    var home = comp.files.root.searchForFolder("home");
                    if (home != null)
                    {
                        home.folders.Clear();
                        home.files.Clear();
                    }
                }
            });
            executor.RegisterExecutor("Computer.file", (exec, info) =>
            {
                var path     = info.Attributes.GetString("path", "home");
                var name     = info.Attributes.GetString("name", "Data").Filter();
                var contents = (info.Content ?? Computer.generateBinaryString(500)).Filter();
                var eduSafe  = info.Attributes.GetBool("EduSafe", true);
                var eduOnly  = info.Attributes.GetBool("EduSafeOnly");

                if ((!eduSafe && Settings.EducationSafeBuild) || (eduOnly && Settings.EducationSafeBuild))
                {
                    return;
                }

                var folder   = comp.getFolderFromPath(path, true);
                var existing = folder.searchForFile(name);
                if (existing != null)
                {
                    existing.data = contents;
                }
                else
                {
                    folder.files.Add(new FileEntry(contents, name));
                }
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.encryptedFile", (exec, info) =>
            {
                var path      = info.Attributes.GetString("path", "home");
                var name      = info.Attributes.GetString("name", "Data").Filter();
                var contents  = (info.Content ?? Computer.generateBinaryString(500)).Filter();
                var header    = info.Attributes.GetString("header", "ERROR");
                var sourceIP  = info.Attributes.GetString("ip", "ERROR");
                var password  = info.Attributes.GetString("pass");
                var extension = info.Attributes.GetString("extension", null);
                var isDouble  = info.Attributes.GetBool("double");

                var encryptedText = FileEncrypter.EncryptString(
                    contents,
                    header,
                    sourceIP,
                    password,
                    extension
                    );
                if (isDouble)
                {
                    encryptedText = FileEncrypter.EncryptString(
                        encryptedText,
                        header,
                        sourceIP,
                        password,
                        "_LAYER2.dec"
                        );
                }

                var folder   = comp.getFolderFromPath(path, true);
                var existing = folder.searchForFile(name);
                if (existing != null)
                {
                    existing.data = encryptedText;
                }
                else
                {
                    folder.files.Add(new FileEntry(encryptedText, name));
                }
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.memoryDumpFile", (exec, info) =>
            {
                var path     = info.Attributes.GetString("path", "home");
                var name     = info.Attributes.GetString("name", "Data").Filter();
                var contents = ReplacementsCommon.LoadMemoryContents(info).GetEncodedFileString();

                var folder   = comp.getFolderFromPath(path, true);
                var existing = folder.searchForFile(name);
                if (existing != null)
                {
                    existing.data = contents;
                }
                else
                {
                    folder.files.Add(new FileEntry(contents, name));
                }
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.customthemefile", (exec, info) =>
            {
                var path     = info.Attributes.GetString("path", "home");
                var name     = info.Attributes.GetString("name", "Data").Filter();
                var contents = ThemeManager.getThemeDataStringForCustomTheme(info.Attributes.GetOrThrow("themePath", "Invalid theme path for customthemefile"));
                if (contents == null)
                {
                    throw new FormatException("Invalid theme path for customthemefile");
                }

                var folder   = comp.getFolderFromPath(path, true);
                var existing = folder.searchForFile(name);
                if (existing != null)
                {
                    existing.data = contents;
                }
                else
                {
                    folder.files.Add(new FileEntry(contents, name));
                }
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.positionNear", (exec, info) =>
            {
                var nearNodeId    = info.Attributes.GetString("target");
                var position      = info.Attributes.GetInt("position") + 1;
                var total         = info.Attributes.GetInt("total", 3);
                var force         = info.Attributes.GetBool("force");
                var extraDistance = Math.Max(-1f, Math.Min(1f, info.Attributes.GetFloat("extraDistance")));

                var sourceComp = comp;
                var origOs     = os;

                ComputerLoader.postAllLoadedActions += () =>
                {
                    var nearNode = Programs.getComputer(os, nearNodeId);
                    if (nearNode != null)
                    {
                        sourceComp.location = nearNode.location + Corporation.getNearbyNodeOffset(nearNode.location, position, total, origOs.netMap, extraDistance, force);
                    }
                };
            });
            executor.RegisterExecutor("Computer.proxy", (exec, info) =>
            {
                var time = info.Attributes.GetFloat("time", 1f);
                if (time > 0f)
                {
                    comp.addProxy(Computer.BASE_PROXY_TICKS * time);
                }
                else
                {
                    comp.hasProxy    = false;
                    comp.proxyActive = false;
                }
            });
            executor.RegisterExecutor("Computer.portsForCrack", (exec, info) =>
            {
                var num = info.Attributes.GetInt("val", -1);
                if (num != -1)
                {
                    comp.portsNeededForCrack = num - 1;
                }
            });
            executor.RegisterExecutor("Computer.firewall", (exec, info) =>
            {
                var level = info.Attributes.GetInt("level", 1);
                if (level > 0)
                {
                    if (info.Attributes.TryGetValue("solution", out var solution))
                    {
                        comp.addFirewall(level, solution, info.Attributes.GetFloat("additionalTime"));
                    }
                    else
                    {
                        comp.addFirewall(level);
                    }
                }
                else
                {
                    comp.firewall = null;
                }
            });
            executor.RegisterExecutor("Computer.link", (exec, info) =>
            {
                var linked = Programs.getComputer(os, info.Attributes.GetString("target"));
                if (linked != null)
                {
                    comp.links.Add(os.netMap.nodes.IndexOf(linked));
                }
            });
            executor.RegisterExecutor("Computer.dlink", (exec, info) =>
            {
                var linked = info.Attributes.GetString("target");
                var source = comp;
                var origOS = os;

                ComputerLoader.postAllLoadedActions += () =>
                {
                    var linkedNode = Programs.getComputer(os, linked);
                    if (linkedNode != null)
                    {
                        source.links.Add(origOS.netMap.nodes.IndexOf(linkedNode));
                    }
                };
            });
            executor.RegisterExecutor("Computer.trace", (exec, info) =>
            {
                comp.traceTime = info.Attributes.GetFloat("time", 1f);
            });
            executor.RegisterExecutor("Computer.adminPass", (exec, info) =>
            {
                comp.setAdminPassword(info.Attributes.GetString("pass", PortExploits.getRandomPassword()));
            });
            executor.RegisterExecutor("Computer.admin", (exec, info) => AdministratorManager.LoadAdministrator(info, comp, os));
            executor.RegisterExecutor("Computer.ports", (exec, info) =>
            {
                PortManager.LoadPortsFromStringVanilla(comp, info.Content);
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.portRemap", (exec, info) =>
            {
                PortManager.LoadPortRemapsFromStringVanilla(comp, info.Content);
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.PFPorts", (exec, info) =>
            {
                if (info.Children.Count != 0)
                {
                    PortManager.LoadPortsFromChildren(comp, info.Children, info.Attributes.GetBool("replace"));
                }
                else
                {
                    PortManager.LoadPortsFromString(comp, info.Content, info.Attributes.GetBool("replace"));
                }
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.ExternalCounterpart", (exec, info) =>
            {
                comp.externalCounterpart = new ExternalCounterpart(info.Attributes.GetString("name"), ExternalCounterpart.getIPForServerName(info.Attributes.GetString("id")));
            });
            executor.RegisterExecutor("Computer.account", (exec, info) =>
            {
                var username   = info.Attributes.GetString("username", "ERROR").Filter();
                var pass       = info.Attributes.GetString("password", "ERROR").Filter();
                var typeString = info.Attributes.GetString("type").ToLower();
                byte type      = 0;
                switch (typeString)
                {
                case "admin":
                    type = 0;
                    break;

                case "all":
                    type = 1;
                    break;

                case "mail":
                    type = 2;
                    break;

                case "missionlist":
                    type = 3;
                    break;

                default:
                    type = info.Attributes.GetByte("type", 0);
                    break;
                }

                var noneExists = true;
                for (int i = 0; i < comp.users.Count; i++)
                {
                    var user = comp.users[i];
                    if (user.name == username)
                    {
                        user.pass = pass;
                        user.type = type;

                        comp.users[i] = user;

                        if (username == "admin")
                        {
                            comp.adminPass = pass;
                        }

                        noneExists = false;
                    }
                }

                if (noneExists)
                {
                    comp.users.Add(new UserDetail(username, pass, type));
                }
            });
            executor.RegisterExecutor("Computer.tracker", (exec, info) => comp.HasTracker = true);
            executor.RegisterExecutor("Computer.missionListingServer", (exec, info) =>
            {
                comp.daemons.Add(new MissionListingServer(
                                     comp,
                                     info.Attributes.GetString("name", "ERROR"),
                                     info.Attributes.GetString("group", "ERROR"),
                                     os,
                                     info.Attributes.GetBool("public")
                                     )
                {
                    missionAssigner = info.Attributes.GetBool("assigner")
                });
            });
            executor.RegisterExecutor("Computer.variableMissionListingServer", (exec, info) =>
            {
                comp.daemons.Add(new MissionListingServer(
                                     comp,
                                     info.Attributes.GetString("name", null).Filter(),
                                     info.Attributes.GetString("iconPath", null),
                                     info.Attributes.GetString("articleFolderPath", null),
                                     info.Attributes.GetColor("color", Color.IndianRed).Value,
                                     os,
                                     info.Attributes.GetBool("public"),
                                     info.Attributes.GetBool("assigner")
                                     )
                {
                    listingTitle = info.Attributes.GetString("title", null)
                });
            });
            executor.RegisterExecutor("Computer.missionHubServer", (exec, info) =>
            {
                var missionPath = ExtensionLoader.ActiveExtensionInfo.FolderPath + "/" + info.Attributes.GetString("missionFolderPath", null);
                missionPath     = missionPath.Replace("\\", "/");
                if (!missionPath.EndsWith("/"))
                {
                    missionPath += "/";
                }

                comp.daemons.Add(new MissionHubServer(
                                     comp,
                                     info.Attributes.GetString("serviceName", null),
                                     info.Attributes.GetString("groupName", null).Filter(),
                                     os
                                     )
                {
                    MissionSourceFolderPath = missionPath,
                    themeColor           = info.Attributes.GetColor("themeColor", Color.PaleTurquoise).Value,
                    themeColorBackground = info.Attributes.GetColor("backgroundColor", Color.PaleTurquoise).Value,
                    themeColorLine       = info.Attributes.GetColor("lineColor", Color.PaleTurquoise).Value,
                    allowAbandon         = info.Attributes.GetBool("allowAbandon", true)
                });
            });
            executor.RegisterExecutor("Computer.mailServer", (exec, info) =>
            {
                var ms = new MailServer(
                    comp,
                    info.Attributes.GetString("name", "Mail Server"),
                    os
                    )
                {
                    shouldGenerateJunkEmails = info.Attributes.GetBool("generateJunk", true),
                };

                var color = info.Attributes.GetColor("color", null);
                if (color != null)
                {
                    ms.setThemeColor(color.Value);
                }

                foreach (var emailInfo in info.Children.Where(x => x.Name == "email"))
                {
                    var sender  = emailInfo.Attributes.GetString("sender", "UNKNOWN").Filter();
                    var subject = emailInfo.Attributes.GetString("subject", "UNKNOWN").Filter();
                    var content = (emailInfo.Content ?? "UNKNOWN").Filter();
                    if (emailInfo.Attributes.TryGetValue("recipient", out var recp))
                    {
                        recp             = recp.Filter();
                        var email        = MailServer.generateEmail(subject, content, sender);
                        ms.setupComplete = (System.Action)Delegate.Combine(ms.setupComplete, (System.Action)(() =>
                        {
                            ms.addMail(email, recp);
                        }));
                    }
                }

                comp.daemons.Add(ms);
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.addEmailDaemon", (exec, info) =>
            {
                comp.daemons.Add(new AddEmailDaemon(comp, "Final Task", os));
            });
            executor.RegisterExecutor("Computer.deathRowDatabase", (exec, info) =>
            {
                comp.daemons.Add(new DeathRowDatabaseDaemon(comp, "Death Row Database", os));
            });
            executor.RegisterExecutor("Computer.academicDatabase", (exec, info) =>
            {
                comp.daemons.Add(new AcademicDatabaseDaemon(comp, "International Academic Database", os));
            });
            executor.RegisterExecutor("Computer.ispSystem", (exec, info) =>
            {
                comp.daemons.Add(new ISPDaemon(comp, os));
            });
            executor.RegisterExecutor("Computer.messageBoard", (exec, info) =>
            {
                var messageBoard = new MessageBoardDaemon(comp, os)
                {
                    name      = info.Attributes.GetString("name", "Anonymous"),
                    BoardName = info.Attributes.GetString("name", "Anonymous")
                };

                foreach (var message in info.Children.Where(x => x.Name == "thread"))
                {
                    var path = message.Content ?? "UNKNOWN";
                    if (Settings.IsInExtensionMode)
                    {
                        path = ExtensionLoader.ActiveExtensionInfo.FolderPath + "/" + path;
                    }
                    else if (!path.StartsWith("Content/Missions/"))
                    {
                        path = "Content/Missions/" + path;
                    }

                    messageBoard.AddThread(Utils.readEntireFile(path));
                }

                comp.daemons.Add(messageBoard);
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.addAvconDemoEndDaemon", (exec, info) =>
            {
                comp.daemons.Add(new AvconDemoEndDaemon(comp, "Demo End", os));
            });
            executor.RegisterExecutor("Computer.addWebServer", (exec, info) =>
            {
                var webServer = new WebServerDaemon(
                    comp,
                    info.Attributes.GetString("name", "Web Server"),
                    os,
                    info.Attributes.GetOrThrow("url", "addWebServer requires a url")
                    );
                webServer.registerAsDefaultBootDaemon();
                comp.daemons.Add(webServer);
            });
            executor.RegisterExecutor("Computer.addOnlineWebServer", (exec, info) =>
            {
                var onlineWebServer = new OnlineWebServerDaemon(
                    comp,
                    info.Attributes.GetString("name", "Web Server"),
                    os
                    );
                if (info.Attributes.TryGetValue("url", out var url))
                {
                    onlineWebServer.setURL(url);
                }
                onlineWebServer.registerAsDefaultBootDaemon();
                comp.daemons.Add(onlineWebServer);
            });
            executor.RegisterExecutor("Computer.uploadServerDaemon", (exec, info) =>
            {
                var uploadServer = new UploadServerDaemon(
                    comp,
                    info.Attributes.GetString("name", "File Upload Server"),
                    info.Attributes.GetColor("color", new Color(0, 94, 38)).Value,
                    os,
                    info.Attributes.GetString("folder", null),
                    info.Attributes.GetBool("needsAuth")
                    )
                {
                    hasReturnViewButton = info.Attributes.GetBool("hasReturnViewButton")
                };

                uploadServer.registerAsDefaultBootDaemon();
                comp.daemons.Add(uploadServer);
            });
            executor.RegisterExecutor("Computer.MedicalDatabase", (exec, info) =>
            {
                comp.daemons.Add(new MedicalDatabaseDaemon(comp, os));
            });
            executor.RegisterExecutor("Computer.HeartMonitor", (exec, info) =>
            {
                comp.daemons.Add(new HeartMonitorDaemon(comp, os)
                {
                    PatientID = info.Attributes.GetString("patient", "UNKNOWN")
                });
            });
            executor.RegisterExecutor("Computer.PointClicker", (exec, info) =>
            {
                comp.daemons.Add(new PointClickerDaemon(comp, "Point Clicker!", os));
            });
            executor.RegisterExecutor("Computer.SongChangerDaemon", (exec, info) =>
            {
                comp.daemons.Add(new SongChangerDaemon(comp, os));
            });
            executor.RegisterExecutor("Computer.DHSDaemon", (exec, info) =>
            {
                if (!DLC1SessionUpgrader.HasDLC1Installed)
                {
                    throw new NotSupportedException("Labyrinths DLC must be installed for DHSDaemon!");
                }

                var dlcHub = new DLCHubServer(
                    comp,
                    "DHS",
                    info.Attributes.GetString("groupName", "UNKNOWN"),
                    os
                    )
                {
                    AddsFactionPointForMissionCompleteion = info.Attributes.GetBool("addsFactionPointOnMissionComplete", true),
                    AutoClearMissionsOnSingleComplete     = info.Attributes.GetBool("autoClearMissionsOnPlayerComplete", true),
                    AllowContractAbbandon = info.Attributes.GetBool("allowContractAbbandon"),
                    themeColor            = info.Attributes.GetColor("themeColor", new Color(38, 201, 155)).Value
                };

                foreach (var userInfo in info.Children.Where(x => x.Name.ToLower() == "user" || x.Name.ToLower() == "agent"))
                {
                    if (userInfo.Attributes.TryGetValue("name", out var name))
                    {
                        dlcHub.AddAgent(
                            name.Filter(),
                            userInfo.Attributes.GetString("pass", "password").Filter(),
                            userInfo.Attributes.GetColor("color", Color.LightGreen).Value
                            );
                    }
                }

                comp.daemons.Add(dlcHub);
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.CustomConnectDisplayDaemon", (exec, info) =>
            {
                comp.daemons.Add(new CustomConnectDisplayDaemon(comp, os));
            });
            executor.RegisterExecutor("Computer.DatabaseDaemon", (exec, info) =>
            {
                if (!DLC1SessionUpgrader.HasDLC1Installed)
                {
                    throw new NotSupportedException("Labyrinths DLC must be installed for DatabaseDaemon!");
                }

                comp.daemons.Add(new DatabaseDaemon(
                                     comp,
                                     os,
                                     info.Attributes.GetString("Name", "Database"),
                                     DatabaseDaemon.GetDatabasePermissionsFromString(info.Attributes.GetString("Permissions")),
                                     info.Attributes.GetString("DataType", null),
                                     info.Attributes.GetString("Foldername", null),
                                     info.Attributes.GetColor("Color")
                                     )
                {
                    adminResetEmailHostID      = info.Attributes.GetString("AdminEmailHostID", null),
                    adminResetPassEmailAccount = info.Attributes.GetString("AdminEmailAccount"),
                    Dataset = info.Children.Count == 0 ? null : info.Children.Cast <object>().ToList()
                });
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.WhitelistAuthenticatorDaemon", (exec, info) =>
            {
                comp.daemons.Add(new WhitelistConnectionDaemon(comp, os)
                {
                    RemoteSourceIP      = info.Attributes.GetString("Remote", null),
                    AuthenticatesItself = info.Attributes.GetBool("SelfAuthenticating", true)
                });
            });
            executor.RegisterExecutor("Computer.MarkovTextDaemon", (exec, info) =>
            {
                comp.daemons.Add(new MarkovTextDaemon(
                                     comp,
                                     os,
                                     info.Attributes.GetString("Name", null),
                                     info.Attributes.GetString("SourceFilesContentFolder", null)
                                     ));
            });
            executor.RegisterExecutor("Computer.IRCDaemon", (exec, info) =>
            {
                var irc = new IRCDaemon(comp, os, info.Attributes.GetString("name", "IRC Server"))
                {
                    ThemeColor    = info.Attributes.GetColor("themeColor", new Color(184, 2, 141)).Value,
                    RequiresLogin = info.Attributes.GetBool("needsLogin", false)
                };

                foreach (var child in info.Children)
                {
                    switch (child.Name.ToLower())
                    {
                    case "user":
                    case "agent":
                        if (child.Attributes.TryGetValue("name", out var name))
                        {
                            irc.UserColors.Add(name.Filter(), child.Attributes.GetColor("color", Color.LightGreen).Value);
                        }
                        break;

                    case "post":
                        if (child.Content != null && child.Attributes.TryGetValue("user", out var user))
                        {
                            irc.StartingMessages.Add(new KeyValuePair <string, string>(user.Filter(), child.Content.Filter()));
                        }
                        break;
                    }
                }

                comp.daemons.Add(irc);
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.AircraftDaemon", (exec, info) =>
            {
                if (!DLC1SessionUpgrader.HasDLC1Installed)
                {
                    throw new NotSupportedException("Labrinths DLC has to be installed for aircraft daemon!");
                }

                comp.daemons.Add(new AircraftDaemon(
                                     comp,
                                     os,
                                     info.Attributes.GetString("Name", null),
                                     info.Attributes.GetVector("OriginX", "OriginY", Vector2.Zero).Value,
                                     info.Attributes.GetVector("DestX", "DestY", Vector2.One * 0.5f).Value,
                                     info.Attributes.GetFloat("Progress", 0.5f)
                                     ));
            });
            executor.RegisterExecutor("Computer.LogoCustomConnectDisplayDaemon", (exec, info) =>
            {
                comp.daemons.Add(new LogoCustomConnectDisplayDaemon(
                                     comp,
                                     os,
                                     info.Attributes.GetString("logo", null),
                                     info.Attributes.GetString("title", null),
                                     info.Attributes.GetBool("overdrawLogo"),
                                     info.Attributes.GetString("buttonAlignment", null)
                                     ));
            });
            executor.RegisterExecutor("Computer.LogoDaemon", (exec, info) =>
            {
                comp.daemons.Add(new LogoDaemon(
                                     comp,
                                     os,
                                     comp.name,
                                     info.Attributes.GetBool("ShowsTitle", true),
                                     info.Attributes.GetString("LogoImagePath", null)
                                     )
                {
                    TextColor = info.Attributes.GetColor("TextColor", Color.White).Value,
                    BodyText  = info.Content
                });
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.DLCCredits", (exec, info) =>
            {
                DLCCreditsDaemon credits;
                string title, text = null;
                if (info.Attributes.TryGetValue("Title", out title) || info.Attributes.TryGetValue("ButtonText", out text))
                {
                    credits = new DLCCreditsDaemon(comp, os, title.Filter(), text.Filter());
                }
                else
                {
                    credits = new DLCCreditsDaemon(comp, os);
                }

                credits.ConditionalActionsToLoadOnButtonPress = info.Attributes.GetString("ConditionalActionSetToRunOnButtonPressPath", null);
                comp.daemons.Add(credits);
            });
            executor.RegisterExecutor("Computer.CreditsDaemon", (exec, info) =>
            {
                DLCCreditsDaemon credits;
                string title, text = null;
                if (info.Attributes.TryGetValue("Title", out title) || info.Attributes.TryGetValue("ButtonText", out text))
                {
                    credits = new DLCCreditsDaemon(comp, os, title.Filter(), text.Filter());
                }
                else
                {
                    credits = new DLCCreditsDaemon(comp, os);
                }

                credits.ConditionalActionsToLoadOnButtonPress = info.Attributes.GetString("ConditionalActionSetToRunOnButtonPressPath", null);
                comp.daemons.Add(credits);
            });
            executor.RegisterExecutor("Computer.FastActionHost", (exec, info) =>
            {
                comp.daemons.Add(new FastActionHost(comp, os, comp.name));
            });
            executor.RegisterExecutor("Computer.PorthackHeart", (exec, info) =>
            {
                comp.daemons.Add(new PorthackHeartDaemon(comp, os));
            });
            executor.RegisterExecutor("Computer.Memory", (exec, info) => comp.Memory = ReplacementsCommon.LoadMemoryContents(info), ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.eosDevice", (exec, info) =>
            {
                eos = new Computer(
                    info.Attributes.GetString("name", "Unregistered eOS Device"),
                    NetworkMap.generateRandomIP(),
                    os.netMap.getRandomPosition(),
                    0,
                    5,
                    os
                    )
                {
                    idName              = info.Attributes.GetString("id", comp.idName + "_eos"),
                    icon                = info.Attributes.GetString("icon", "ePhone"),
                    location            = comp.location + Corporation.getNearbyNodeOffset(comp.location, Utils.random.Next(12), 12, os.netMap),
                    portsNeededForCrack = 2
                };

                PortManager.LoadPortsFromStringVanilla(eos, "22,3659");
                eos.setAdminPassword(info.Attributes.GetString("passOverride", "alpine"));

                EOSComp.GenerateEOSFilesystem(eos);
                if (info.Attributes.GetBool("empty", false))
                {
                    var apps = eos.files.root.searchForFolder("eos").searchForFolder("apps");
                    apps?.folders.Clear();
                    apps?.files.Clear();
                }

                os.netMap.nodes.Add(eos);

                if (comp.attatchedDeviceIDs != null)
                {
                    comp.attatchedDeviceIDs += ",";
                }
                comp.attatchedDeviceIDs += eos.idName;
            });
            executor.RegisterExecutor("Computer.eosDevice.note", (exec, info) =>
            {
                var noteFile    = info.Attributes.GetString("filename", null);
                var content     = info.Content.TrimStart().Filter();
                var notesFolder = eos.files.root.searchForFolder("eos").searchForFolder("notes");

                if (noteFile == null)
                {
                    var firstNewline = content.IndexOf('\n');
                    if (firstNewline == -1)
                    {
                        firstNewline = content.Length;
                    }
                    noteFile = content.Substring(0, firstNewline);
                    if (noteFile.Length > 50)
                    {
                        noteFile = noteFile.Substring(0, 47) + "...";
                    }
                }
                notesFolder.files.Add(new FileEntry(content, noteFile));
            }, ParseOption.ParseInterior);
            executor.RegisterExecutor("Computer.eosDevice.mail", (exec, info) =>
            {
                var username   = info.Attributes.GetString("username", null);
                var password   = info.Attributes.GetString("pass", null);
                var mailFolder = eos.files.root.searchForFolder("eos").searchForFolder("mail");

                mailFolder.files.Add(new FileEntry(
                                         $"MAIL ACCOUNT : {username}\nAccount   :{username}\nPassword :{password}\nLast Sync :{DateTime.Now.ToString()}\n\n{Computer.generateBinaryString(512)}",
                                         username + ".act"
                                         ));
            });
            executor.RegisterExecutor("Computer.eosDevice.file", (exec, info) =>
            {
                eos.getFolderFromPath(info.Attributes.GetString("path", "home")).files.Add(new FileEntry(
                                                                                               (info.Content ?? "").Filter().TrimStart(),
                                                                                               info.Attributes.GetString("name", null)
                                                                                               ));
            }, ParseOption.ParseInterior);
        }
 public static string GetDatabasePersonalFilename(this DatabaseDaemon daemon, Person input)
 => Utils.GetNonRepeatingFilename((input.firstName + '_' + input.lastName).ToLower(), ".rec", daemon.DatasetFolder);
 public static string GetDatabaseFilename(this DatabaseDaemon daemon, string input)
 => Utils.GetNonRepeatingFilename(input.Replace(" ", "_").ToLower(), ".rec", daemon.DatasetFolder);