145 lines
5.1 KiB
C#
145 lines
5.1 KiB
C#
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<D2AccountPersisted> AccountList { get; set; } = new List<D2AccountPersisted>();
|
|
}
|
|
|
|
static class D2AccountsXmlStore
|
|
{
|
|
public static string DefaultPath =>
|
|
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "accounts.xml");
|
|
|
|
public static List<D2Account> Load(string path)
|
|
{
|
|
if (!File.Exists(path))
|
|
return new List<D2Account>();
|
|
|
|
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<D2Account>();
|
|
|
|
var result = new List<D2Account>(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;
|
|
}
|
|
}
|
|
|
|
/// <summary>Builds XML from accounts; encrypts only here from <see cref="D2Account.Password"/> when non-empty.</summary>
|
|
public static void Save(string path, IEnumerable<D2Account> accounts)
|
|
{
|
|
var dir = Path.GetDirectoryName(path);
|
|
if (!string.IsNullOrEmpty(dir))
|
|
Directory.CreateDirectory(dir);
|
|
|
|
var persisted = (accounts ?? Enumerable.Empty<D2Account>())
|
|
.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<D2Character> MapCharactersFromPersisted(List<D2CharacterPersisted> list)
|
|
{
|
|
if (list == null || list.Count == 0)
|
|
return new List<D2Character>();
|
|
var result = new List<D2Character>(list.Count);
|
|
foreach (var cp in list)
|
|
{
|
|
if (cp == null)
|
|
continue;
|
|
var missions = new List<D2Mission>();
|
|
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<D2CharacterPersisted> MapCharactersToPersisted(List<D2Character> list)
|
|
{
|
|
if (list == null || list.Count == 0)
|
|
return null;
|
|
var result = new List<D2CharacterPersisted>(list.Count);
|
|
foreach (var c in list)
|
|
{
|
|
if (c == null)
|
|
continue;
|
|
var mpList = new List<D2MissionPersisted>();
|
|
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;
|
|
}
|
|
}
|
|
}
|