using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml.Serialization; namespace D2Multi { [XmlRoot("Accounts")] public class D2AccountsRoot { [XmlElement("Account")] public List AccountList { get; set; } = new List(); } static class D2AccountsXmlStore { public static string DefaultPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "accounts.xml"); public static List Load(string path) { if (!File.Exists(path)) return new List(); using (var stream = File.OpenRead(path)) { var ser = new XmlSerializer(typeof(D2AccountsRoot)); var root = (D2AccountsRoot)ser.Deserialize(stream); if (root?.AccountList == null) return new List(); var result = new List(root.AccountList.Count); foreach (var p in root.AccountList) { var cipher = p?.EncryptedPassword ?? string.Empty; result.Add(new D2Account { Name = p?.Name, Email = p?.Email, EncryptedPassword = cipher, Password = D2AccountCrypto.Unprotect(cipher), Characters = MapCharactersFromPersisted(p?.Characters), }); } return result; } } /// Builds XML from accounts; encrypts only here from when non-empty. public static void Save(string path, IEnumerable accounts) { var dir = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); var persisted = (accounts ?? Enumerable.Empty()) .Select(ToPersistedForXml) .ToList(); var root = new D2AccountsRoot { AccountList = persisted }; using (var stream = File.Create(path)) { var ser = new XmlSerializer(typeof(D2AccountsRoot)); ser.Serialize(stream, root); } } static D2AccountPersisted ToPersistedForXml(D2Account a) { string encrypted; if (!string.IsNullOrEmpty(a?.Password)) encrypted = D2AccountCrypto.Protect(a.Password); else encrypted = a?.EncryptedPassword ?? string.Empty; return new D2AccountPersisted { Name = a?.Name, Email = a?.Email, EncryptedPassword = encrypted, Characters = MapCharactersToPersisted(a?.Characters), }; } static List MapCharactersFromPersisted(List list) { if (list == null || list.Count == 0) return new List(); var result = new List(list.Count); foreach (var cp in list) { if (cp == null) continue; var missions = new List(); if (cp.Missions != null) { foreach (var mp in cp.Missions) { if (mp == null) continue; missions.Add(new D2Mission { Level = mp.Level, A1_Enpowered = mp.A1_Enpowered, A5_Socket = mp.A5_Socket, }); } } result.Add(new D2Character { Name = cp.Name, Class = cp.Class, Missions = missions }); } return result; } static List MapCharactersToPersisted(List list) { if (list == null || list.Count == 0) return null; var result = new List(list.Count); foreach (var c in list) { if (c == null) continue; var mpList = new List(); if (c.Missions != null) { foreach (var m in c.Missions) { if (m == null) continue; mpList.Add(new D2MissionPersisted { Level = m.Level, A1_Enpowered = m.A1_Enpowered, A5_Socket = m.A5_Socket, }); } } result.Add(new D2CharacterPersisted { Name = c.Name, Class = c.Class, Missions = mpList }); } return result.Count == 0 ? null : result; } } }