-
Notifications
You must be signed in to change notification settings - Fork 12
/
DoomEternalSavePath.cs
148 lines (124 loc) · 6.64 KB
/
DoomEternalSavePath.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;
namespace DOOMSaveManager
{
public enum DoomEternalSavePlatform
{
BethesdaNet,
Steam,
}
public class DoomEternalSavePath
{
public string Identifier;
public string FullPath;
public DoomEternalSavePlatform Platform;
public bool Encrypted = true;
public static string BnetSavePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Saved Games", "id Software", "DOOMEternal", "base", "savegame");
public static string SteamSavePath = Path.Combine(Utilities.GetSteamPath(), "userdata");
public DoomEternalSavePath(string id, DoomEternalSavePlatform platform, bool encrypted = true) {
Identifier = id;
Platform = platform;
Encrypted = encrypted;
if (Identifier == "savegame.unencrypted") {
Encrypted = false;
FullPath = Path.Combine(BnetSavePath + ".unencrypted", Environment.UserName);
} else if (platform == DoomEternalSavePlatform.BethesdaNet)
FullPath = Path.Combine(BnetSavePath, Identifier);
else if (platform == DoomEternalSavePlatform.Steam)
FullPath = Path.Combine(SteamSavePath, Utilities.Id64ToId3(Identifier), DoomEternal.SteamGameID.ToString(), "remote");
}
public string[] GetAbsolutePaths() => Directory.GetFiles(FullPath, "*.*", SearchOption.AllDirectories);
public string[] GetRelativePaths() => GetAbsolutePaths().Select(single => single.Replace(FullPath, "").Substring(1)).ToArray();
public bool Exists() => Directory.Exists(FullPath);
public void Compress(string filename) {
using (var fsOut = File.Create(filename))
using (var zs = new ZipOutputStream(fsOut)) {
zs.SetLevel(3);
foreach (var single in GetAbsolutePaths()) {
if (single.EndsWith("-BACKUP"))
continue;
byte[] fileData = File.ReadAllBytes(single);
string relPath = single.Replace(FullPath, "").Substring(1);
if (Platform == DoomEternalSavePlatform.BethesdaNet && Encrypted)
fileData = Crypto.DecryptAndVerify($"{Identifier}PAINELEMENTAL{Path.GetFileName(single)}", fileData);
else if (Platform == DoomEternalSavePlatform.Steam && Encrypted)
fileData = Crypto.DecryptAndVerify($"{Identifier}MANCUBUS{Path.GetFileName(single)}", fileData);
var fi = new FileInfo(single);
var entryName = ZipEntry.CleanName(relPath);
var ze = new ZipEntry(entryName);
ze.Size = fileData.Length;
ze.DateTime = fi.LastWriteTime;
zs.PutNextEntry(ze);
var buffer = new byte[4096];
using (var dataIn = new MemoryStream(fileData)) {
StreamUtils.Copy(dataIn, zs, buffer);
}
zs.CloseEntry();
}
}
}
public void Decompress(string filename) {
using (Stream fsIn = File.OpenRead(filename))
using (var zf = new ZipFile(fsIn)) {
foreach (ZipEntry ze in zf) {
if (!ze.IsFile)
continue;
string entryFileName = ze.Name;
var fullZipToPath = Path.Combine(FullPath, entryFileName);
var directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0) {
Directory.CreateDirectory(directoryName);
}
var buffer = new byte[4096];
using (var zs = zf.GetInputStream(ze))
using (MemoryStream dataOut = new MemoryStream()) {
StreamUtils.Copy(zs, dataOut, buffer);
byte[] fileData = dataOut.ToArray();
if (Platform == DoomEternalSavePlatform.BethesdaNet && Encrypted)
fileData = Crypto.EncryptAndDigest($"{Identifier}PAINELEMENTAL{Path.GetFileName(entryFileName)}", fileData);
else if (Platform == DoomEternalSavePlatform.Steam && Encrypted)
fileData = Crypto.EncryptAndDigest($"{Identifier}MANCUBUS{Path.GetFileName(entryFileName)}", fileData);
File.WriteAllBytes(fullZipToPath, fileData);
}
}
}
}
public void Transfer(DoomEternalSavePath dst) {
List<Tuple<string, byte[]>> srcFiles = new List<Tuple<string, byte[]>>();
// read from source
string srcAAD;
if(Platform == DoomEternalSavePlatform.BethesdaNet)
srcAAD = "PAINELEMENTAL";
else if (Platform == DoomEternalSavePlatform.Steam)
srcAAD = "MANCUBUS";
else
throw new Exception("Unsupported source platform specified!");
foreach (var single in GetAbsolutePaths()) {
if (Encrypted)
srcFiles.Add(new Tuple<string, byte[]>(single.Replace(FullPath, "").Substring(1), Crypto.DecryptAndVerify($"{Identifier}{srcAAD}{Path.GetFileName(single)}", File.ReadAllBytes(single))));
else
srcFiles.Add(new Tuple<string, byte[]>(single.Replace(FullPath, "").Substring(1), File.ReadAllBytes(single)));
}
// copy to destination
string dstAAD;
if (dst.Platform == DoomEternalSavePlatform.BethesdaNet)
dstAAD = "PAINELEMENTAL";
else if (dst.Platform == DoomEternalSavePlatform.Steam)
dstAAD = "MANCUBUS";
else
throw new Exception("Unsupported destination platform specified!");
foreach (var single in srcFiles) {
Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(dst.FullPath, single.Item1)));
if (dst.Encrypted)
File.WriteAllBytes(Path.Combine(dst.FullPath, single.Item1), Crypto.EncryptAndDigest($"{dst.Identifier}{dstAAD}{Path.GetFileName(single.Item1)}", single.Item2));
else
File.WriteAllBytes(Path.Combine(dst.FullPath, single.Item1), single.Item2);
}
}
public static void Transfer(DoomEternalSavePath src, DoomEternalSavePath dst) => src.Transfer(dst);
}
}