mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Net update
This commit is contained in:
parent
20a4473abf
commit
764b551767
6 changed files with 156 additions and 78 deletions
|
@ -17,6 +17,7 @@ namespace Net
|
|||
new CliOption("did", 1, (o, a) => o.DeviceId = ParseTitleId(a[0])),
|
||||
new CliOption("cert", 1, (o, a) => o.CertFile = a[0]),
|
||||
new CliOption("commoncert", 1, (o, a) => o.CommonCertFile = a[0]),
|
||||
new CliOption("token", 1, (o, a) => o.Token = a[0]),
|
||||
new CliOption("metadata", 0, (o, a) => o.GetMetadata = true)
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Net
|
|||
{
|
||||
public class Database
|
||||
{
|
||||
public Dictionary<long, TitleMetadata> Titles { get; set; } = new Dictionary<long, TitleMetadata>();
|
||||
public Dictionary<ulong, TitleMetadata> Titles { get; set; } = new Dictionary<ulong, TitleMetadata>();
|
||||
public DateTime VersionListTime { get; set; }
|
||||
|
||||
public string Serialize()
|
||||
|
@ -30,36 +30,39 @@ namespace Net
|
|||
|
||||
public void ImportVersionList(VersionList list)
|
||||
{
|
||||
foreach (var title in list.titles)
|
||||
foreach (VersionListTitle title in list.titles)
|
||||
{
|
||||
var mainId = long.Parse(title.id, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
long updateId = 0;
|
||||
bool isUpdate = (mainId & 0x800) != 0;
|
||||
if (isUpdate)
|
||||
ulong mainId = ulong.Parse(title.id, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
|
||||
AddTitle(mainId);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddTitle(ulong id, int version = -1)
|
||||
{
|
||||
bool isUpdate = (id & 0x800) != 0;
|
||||
|
||||
if (!Titles.TryGetValue(id, out TitleMetadata titleDb))
|
||||
{
|
||||
titleDb = new TitleMetadata { Id = id };
|
||||
Titles[id] = titleDb;
|
||||
}
|
||||
|
||||
if (version >= 0)
|
||||
{
|
||||
titleDb.MaxVersion = version;
|
||||
|
||||
int minVersion = isUpdate ? 1 : 0;
|
||||
|
||||
int maxVersionShort = titleDb.MaxVersion >> 16;
|
||||
for (int i = minVersion; i <= maxVersionShort; i++)
|
||||
{
|
||||
updateId = mainId;
|
||||
mainId &= ~0x800;
|
||||
}
|
||||
int longVersion = i << 16;
|
||||
|
||||
if (!Titles.TryGetValue(mainId, out TitleMetadata titleDb))
|
||||
{
|
||||
titleDb = new TitleMetadata();
|
||||
Titles[mainId] = titleDb;
|
||||
}
|
||||
|
||||
titleDb.Id = mainId;
|
||||
titleDb.UpdateId = updateId;
|
||||
titleDb.MaxVersion = title.version;
|
||||
|
||||
int maxVersionShort = title.version >> 16;
|
||||
for (int i = 0; i <= maxVersionShort; i++)
|
||||
{
|
||||
var version = i << 16;
|
||||
|
||||
if (!titleDb.Versions.TryGetValue(version, out TitleVersion versionDb))
|
||||
if (!titleDb.Versions.TryGetValue(longVersion, out TitleVersion versionDb))
|
||||
{
|
||||
versionDb = new TitleVersion { Version = version };
|
||||
titleDb.Versions.Add(version, versionDb);
|
||||
versionDb = new TitleVersion { Version = longVersion };
|
||||
titleDb.Versions.Add(longVersion, versionDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,46 +77,21 @@ namespace Net
|
|||
{
|
||||
foreach (string id in titleIds)
|
||||
{
|
||||
var mainId = long.Parse(id, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
long updateId = 0;
|
||||
bool isUpdate = (mainId & 0x800) != 0;
|
||||
if (isUpdate)
|
||||
{
|
||||
updateId = mainId;
|
||||
mainId &= ~0x800;
|
||||
}
|
||||
|
||||
var titleDb = new TitleMetadata();
|
||||
Titles[mainId] = titleDb;
|
||||
|
||||
titleDb.Id = mainId;
|
||||
titleDb.UpdateId = mainId | 0x800;
|
||||
titleDb.MaxVersion = 5 << 16;
|
||||
|
||||
int maxVersionShort = 5;
|
||||
for (int i = 0; i <= maxVersionShort; i++)
|
||||
{
|
||||
var version = i << 16;
|
||||
|
||||
if (!titleDb.Versions.TryGetValue(version, out TitleVersion versionDb))
|
||||
{
|
||||
versionDb = new TitleVersion { Version = version };
|
||||
titleDb.Versions.Add(version, versionDb);
|
||||
}
|
||||
}
|
||||
ulong mainId = ulong.Parse(id, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
AddTitle(mainId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TitleMetadata
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long UpdateId { get; set; }
|
||||
public List<long> AocIds { get; set; } = new List<long>();
|
||||
public ulong Id { get; set; }
|
||||
public int MaxVersion { get; set; }
|
||||
public List<SuperflyInfo> Superfly { get; set; } = new List<SuperflyInfo>();
|
||||
public DateTime SuperflyTime { get; set; }
|
||||
public Dictionary<int, TitleVersion> Versions { get; set; } = new Dictionary<int, TitleVersion>();
|
||||
|
||||
|
||||
public bool IsSuperflyCurrent() => SuperflyTime.AddDays(15) > DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public class TitleVersion
|
||||
|
|
13
Net/Json.cs
13
Net/Json.cs
|
@ -14,6 +14,12 @@ namespace Net
|
|||
var versionList = JsonConvert.DeserializeObject<VersionList>(text);
|
||||
return versionList;
|
||||
}
|
||||
|
||||
public static List<SuperflyInfo> ReadSuperfly(string filename)
|
||||
{
|
||||
string text = File.ReadAllText(filename);
|
||||
return JsonConvert.DeserializeObject<List<SuperflyInfo>>(text);
|
||||
}
|
||||
}
|
||||
|
||||
public class VersionList
|
||||
|
@ -29,4 +35,11 @@ namespace Net
|
|||
public int version { get; set; }
|
||||
public int required_version { get; set; }
|
||||
}
|
||||
|
||||
public class SuperflyInfo
|
||||
{
|
||||
public string title_id { get; set; }
|
||||
public int version { get; set; }
|
||||
public string title_type { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
@ -11,9 +12,10 @@ namespace Net
|
|||
{
|
||||
private X509Certificate2 Certificate { get; set; }
|
||||
private X509Certificate2 CertificateCommon { get; set; }
|
||||
private string Token { get; }
|
||||
private string Eid { get; } = "lp1";
|
||||
private ulong Did { get; }
|
||||
private string Firmware { get; } = "5.1.0-3.0";
|
||||
private string Firmware { get; } = "6.0.0-5.0";
|
||||
private string CachePath { get; } = "titles";
|
||||
private Context ToolCtx { get; }
|
||||
public Database Db { get; }
|
||||
|
@ -24,6 +26,8 @@ namespace Net
|
|||
{
|
||||
ToolCtx = ctx;
|
||||
Did = ctx.Options.DeviceId;
|
||||
Token = ctx.Options.Token;
|
||||
|
||||
if (ctx.Options.CertFile != null)
|
||||
{
|
||||
SetCertificate(ctx.Options.CertFile);
|
||||
|
@ -62,7 +66,7 @@ namespace Net
|
|||
if (stream == null) return null;
|
||||
|
||||
var nca = new Nca(ToolCtx.Keyset, stream, true);
|
||||
Stream sect = nca.OpenSection(0, false);
|
||||
Stream sect = nca.OpenSection(0, false, true);
|
||||
var pfs0 = new Pfs(sect);
|
||||
var file = pfs0.OpenFile(pfs0.Files[0]);
|
||||
|
||||
|
@ -112,7 +116,7 @@ namespace Net
|
|||
if (controlNca == null) return null;
|
||||
|
||||
var nca = new Nca(ToolCtx.Keyset, controlNca, true);
|
||||
var romfs = new Romfs(nca.OpenSection(0, false));
|
||||
var romfs = new Romfs(nca.OpenSection(0, false, true));
|
||||
var controlNacp = romfs.GetFile("/control.nacp");
|
||||
|
||||
var reader = new BinaryReader(new MemoryStream(controlNacp));
|
||||
|
@ -136,6 +140,27 @@ namespace Net
|
|||
return new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
}
|
||||
|
||||
public List<SuperflyInfo> GetSuperfly(ulong titleId)
|
||||
{
|
||||
var filename = GetSuperflyFile(titleId);
|
||||
return Json.ReadSuperfly(filename);
|
||||
}
|
||||
|
||||
public string GetSuperflyFile(ulong titleId)
|
||||
{
|
||||
string titleDir = GetTitleDir(titleId);
|
||||
|
||||
var filePath = Path.Combine(titleDir, $"{titleId:x16}.json");
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
DownloadFile(GetSuperflyUrl(titleId), filePath);
|
||||
}
|
||||
|
||||
if (!File.Exists(filePath)) return null;
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
private void DownloadCnmt(ulong titleId, int version)
|
||||
{
|
||||
var titleDir = GetTitleDir(titleId, version);
|
||||
|
@ -179,9 +204,14 @@ namespace Net
|
|||
}
|
||||
}
|
||||
|
||||
private string GetTitleDir(ulong titleId, int version)
|
||||
private string GetTitleDir(ulong titleId, int version = -1)
|
||||
{
|
||||
return Path.Combine(CachePath, $"{titleId:x16}", $"{version}");
|
||||
if (version >= 0)
|
||||
{
|
||||
return Path.Combine(CachePath, $"{titleId:x16}", $"{version}");
|
||||
}
|
||||
|
||||
return Path.Combine(CachePath, $"{titleId:x16}");
|
||||
}
|
||||
|
||||
public string GetMetaUrl(string ncaId)
|
||||
|
@ -196,6 +226,12 @@ namespace Net
|
|||
return url;
|
||||
}
|
||||
|
||||
public string GetSuperflyUrl(ulong titleId)
|
||||
{
|
||||
string url = $"https://superfly.hac.{Eid}.d4c.nintendo.net/v1/a/{titleId:x16}/dv";
|
||||
return url;
|
||||
}
|
||||
|
||||
public string GetMetadataNcaId(ulong titleId, int version)
|
||||
{
|
||||
string url = $"{GetAtumUrl()}/t/a/{titleId:x16}/{version}?deviceid={Did}";
|
||||
|
@ -239,7 +275,9 @@ namespace Net
|
|||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
request.ClientCertificates.Add(Certificate);
|
||||
request.Accept = "*/*";
|
||||
request.UserAgent = $"NintendoSDK Firmware/{Firmware} (platform:NX; did:{Did}; eid:{Eid})";
|
||||
request.Headers.Add("X-Nintendo-DenebEdgeToken", Token);
|
||||
request.Method = method;
|
||||
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace Net
|
|||
public ulong DeviceId;
|
||||
public string CertFile;
|
||||
public string CommonCertFile;
|
||||
public string Token;
|
||||
public bool GetMetadata;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,14 @@ namespace Net
|
|||
return;
|
||||
}
|
||||
|
||||
var tid = ctx.Options.TitleId;
|
||||
var ver = ctx.Options.Version;
|
||||
if (string.IsNullOrWhiteSpace(ctx.Options.Token))
|
||||
{
|
||||
CliParser.PrintWithUsage("A token must be set.");
|
||||
return;
|
||||
}
|
||||
|
||||
ulong tid = ctx.Options.TitleId;
|
||||
int ver = ctx.Options.Version;
|
||||
|
||||
var net = new NetContext(ctx);
|
||||
var cnmt = net.GetCnmt(tid, ver);
|
||||
|
@ -66,38 +72,79 @@ namespace Net
|
|||
|
||||
private static void GetMetadata(NetContext net, IProgressReport logger = null)
|
||||
{
|
||||
var versionList = net.GetVersionList();
|
||||
VersionList versionList = net.GetVersionList();
|
||||
net.Db.ImportVersionList(versionList);
|
||||
//net.Db.ImportList("titles.txt");
|
||||
net.Save();
|
||||
ReadMetaNcas(net, logger);
|
||||
|
||||
net.Save();
|
||||
}
|
||||
|
||||
foreach (var title in net.Db.Titles.Values)
|
||||
private static void ReadMetaNcas(NetContext net, IProgressReport logger = null)
|
||||
{
|
||||
foreach (TitleMetadata title in net.Db.Titles.Values.ToArray())
|
||||
{
|
||||
foreach (var version in title.Versions.Values.Where(x => x.Exists))
|
||||
if (title.Versions.Count == 0)
|
||||
{
|
||||
var titleId = version.Version == 0 ? title.Id : title.UpdateId;
|
||||
int version = 0;
|
||||
if ((title.Id & 0x800) != 0)
|
||||
{
|
||||
version = 1 << 16;
|
||||
}
|
||||
|
||||
title.Versions.Add(version, new TitleVersion { Version = version });
|
||||
}
|
||||
|
||||
foreach (TitleVersion version in title.Versions.Values.Where(x => x.Exists))
|
||||
{
|
||||
ulong titleId = title.Id;
|
||||
try
|
||||
{
|
||||
var control = net.GetControl((ulong)titleId, version.Version);
|
||||
version.Control = control;
|
||||
if (control == null) version.Exists = false;
|
||||
|
||||
Cnmt meta = net.GetCnmt((ulong)titleId, version.Version);
|
||||
Cnmt meta = net.GetCnmt(titleId, version.Version);
|
||||
version.ContentMetadata = meta;
|
||||
if (meta == null) version.Exists = false;
|
||||
if (meta == null)
|
||||
{
|
||||
version.Exists = false;
|
||||
logger?.LogMessage($"{titleId:x16}v{version.Version} not found.");
|
||||
continue;
|
||||
}
|
||||
|
||||
logger?.LogMessage($"{titleId}v{version.Version}");
|
||||
Nacp control = net.GetControl(titleId, version.Version);
|
||||
version.Control = control;
|
||||
|
||||
if (!net.Db.Titles.ContainsKey(meta.ApplicationTitleId))
|
||||
{
|
||||
net.Db.AddTitle(meta.ApplicationTitleId);
|
||||
logger?.LogMessage($"Found title {meta.ApplicationTitleId:x16}");
|
||||
}
|
||||
|
||||
if (meta.Type == TitleType.Application)
|
||||
{
|
||||
ReadSuperfly(title, net, logger);
|
||||
}
|
||||
|
||||
logger?.LogMessage($"{titleId:x16}v{version.Version}");
|
||||
//Thread.Sleep(300);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger?.LogMessage($"Failed getting {titleId}v{version.Version}\n{ex.Message}");
|
||||
logger?.LogMessage($"Failed getting {titleId:x16}v{version.Version}\n{ex.Message}");
|
||||
}
|
||||
}
|
||||
// net.Save();
|
||||
}
|
||||
}
|
||||
|
||||
net.Save();
|
||||
private static void ReadSuperfly(TitleMetadata titleDb, NetContext net, IProgressReport logger = null)
|
||||
{
|
||||
titleDb.Superfly = net.GetSuperfly(titleDb.Id);
|
||||
|
||||
foreach (SuperflyInfo title in titleDb.Superfly)
|
||||
{
|
||||
ulong id = ulong.Parse(title.title_id, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
net.Db.AddTitle(id, title.version);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenKeyset(Context ctx)
|
||||
|
|
Loading…
Reference in a new issue