protected async Task InternalCreateIRD(string savePath, CancellationToken cancellation, string isoPath = null) { byte[] buffer = new byte[Utilities.SectorSize]; List <FileHash> fileList = new List <FileHash>(); try { // First, get the partition table of this iso using (Stream fs = Open()) { if (fs == null) { return; } PS3CDReader reader = new PS3CDReader(fs); List <DirectoryMemberInformation> files = reader.Members.Where(d => d.IsFile).Distinct().ToList(); StartOfDataSector = files.First().StartSector; EndOfDataSector = files.Last().StartSector + files.Last().TotalSectors; var updateFile = files.FirstOrDefault( d => d.Path.Equals("/PS3_UPDATE/PS3UPDAT.PUP", StringComparison.OrdinalIgnoreCase)); long updateOffset = updateFile != null ? updateFile.StartSector * Utilities.SectorSize : 0; fileList.AddRange(files.Select(d => new FileHash(d.StartSector, d.Length))); if (cancellation.IsCancellationRequested) { return; } IrdFile irdFile = IrdFile.New(); using (Stream s = reader.OpenFile("PS3_GAME\\PARAM.SFO", FileMode.Open, FileAccess.Read)) { ParamSfo sfo = ParamSfo.Load(s); irdFile.AppVersion = sfo.GetStringValue("APP_VER"); irdFile.GameVersion = sfo.GetStringValue("VERSION"); irdFile.GameID = sfo.GetStringValue("TITLE_ID"); irdFile.GameName = sfo.GetStringValue("TITLE"); } Interaction.Instance.ReportMessage("Processing " + (string.IsNullOrEmpty(irdFile.GameName) ? irdFile.GameID : irdFile.GameName)); irdFile.UpdateVersion = Utilities.FindUpdateVersion(fs, updateOffset); using (FileStream isoStream = string.IsNullOrEmpty(isoPath) ? null : new FileStream(isoPath, FileMode.Create, FileAccess.Write)) { if (isoStream != null) { isoStream.SetLength(TotalSectors * Utilities.SectorSize); } using (IOStream ioStream = new IOStream(fs, isoStream)) { ioStream.Seek(0, SeekOrigin.Begin); // Read the header, until StartOfDataSector (in sectors) irdFile.Header = new MemoryStream(); for (int i = 0; i < StartOfDataSector; i++) { int bytesRead = ioStream.Read(buffer, 0, buffer.Length); irdFile.Header.Write(buffer, 0, bytesRead); Interaction.Instance.ReportProgress(i); if (cancellation.IsCancellationRequested) { return; } } irdFile.ExtractAuthData(); // Fix the regions for the actual interesting data Regions.First().Start = (uint)StartOfDataSector; Regions.First().Length -= (uint)StartOfDataSector; Regions.Last().Length = (uint)EndOfDataSector - Regions.Last().Start; // Now, we should calculate the md5 sums of all regions Interaction.Instance.ReportMessage("Calculating hashes for " + Regions.Length + " regions."); for (int i = 0; i < Regions.Length; i++) { // Calculate the hash Interaction.Instance.ReportMessage( "Calculate hash for region " + i + " (" + Regions[i].Start.ToString("X2") + "-" + Regions[i].End.ToString("X2") + ")"); ioStream.Seek(Regions[i].Start * Utilities.SectorSize, SeekOrigin.Begin); using (FileHashStream fhs = new FileHashStream(fileList, Regions[i].Start)) { await Regions[i].CopyRegion(cancellation, ioStream, fhs); if (cancellation.IsCancellationRequested) { return; } irdFile.RegionHashes.Add(Regions[i].SourceHash); Interaction.Instance.ReportMessage("Region " + i + " hash: " + Regions[i].SourceHash.AsString()); } } ioStream.Seek(EndOfDataSector * Utilities.SectorSize, SeekOrigin.Begin); irdFile.Footer = new MemoryStream(); for (long i = EndOfDataSector; i < TotalSectors; i++) { int bytesRead = ioStream.Read(buffer, 0, buffer.Length); irdFile.Footer.Write(buffer, 0, bytesRead); Interaction.Instance.ReportProgress((int)(ioStream.Position / Utilities.SectorSize)); if (cancellation.IsCancellationRequested) { return; } } } } irdFile.FileHashes = fileList.ToDictionary(t => t.StartSector, t => t.Hash); irdFile.Save(savePath); Interaction.Instance.ReportMessage("All done, IRD file saved to " + savePath); } } catch (BadReadException e) { Interaction.Instance.ReportMessage(e.Message, ReportType.Fail); } catch (AuthenticationException e) { Interaction.Instance.ReportMessage(e.Message, ReportType.Fail); } }
public static async Task Upload(CancellationToken cancellation, string filename = null) { string[] filenames; // Find the IRD file if (string.IsNullOrEmpty(filename)) { filenames = await Interaction.Instance.GetIrdFiles(); } else { filenames = new[] { filename } }; if (filenames == null || filenames.Length == 0) { return; } Interaction.Instance.TaskBegin(); int totalSize = (int)filenames.Sum(f => new FileInfo(f).Length); Interaction.Instance.SetProgressMaximum(totalSize); int processedSize = 0; foreach (var f in filenames) { string hash; try { hash = IrdFile.GetHash(f); } catch (FileLoadException) { Interaction.Instance.ReportMessage( "Version of IRD file " + Path.GetFileName(f) + " cannot be handled", ReportType.Fail); continue; } byte[] content = File.ReadAllBytes(f); Encryption enc = new Encryption(); enc.Encrypt(content, hash); try { string authInfo = string.Format("{0}:{1}", enc.PublicKey.Join().Md5().AsString(), enc.EncryptedKey.AsString()); HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(URL); wr.Method = "POST"; wr.Headers["Authentication"] = "K3Y " + Convert.ToBase64String(Encoding.ASCII.GetBytes(authInfo)); using (Stream s = await wr.GetRequestStreamAsync()) { if (cancellation.IsCancellationRequested) { return; } int bytesToWrite = enc.EncryptedContent.Length; totalSize += bytesToWrite - content.Length; Interaction.Instance.SetProgressMaximum(totalSize); int bytesWritten = 0; while (bytesToWrite > 0) { int l = bytesToWrite > 2048 ? 2048 : bytesToWrite; await s.WriteAsync(enc.EncryptedContent, bytesWritten, l); bytesWritten += l; bytesToWrite -= l; processedSize += l; Interaction.Instance.ReportProgress(processedSize); if (cancellation.IsCancellationRequested) { return; } } } using (HttpWebResponse response = (HttpWebResponse)await wr.GetResponseAsync()) { // Fetch the response string resp = GetResponseString(response); if (response.StatusCode != HttpStatusCode.OK) { Interaction.Instance.ReportMessage(Path.GetFileName(f) + ": IRD file upload failed: " + (string.IsNullOrEmpty(resp) ? response.StatusDescription : resp), ReportType.Fail); } else { Interaction.Instance.ReportMessage(Path.GetFileName(f) + ": IRD file successfully uploaded", ReportType.Success); ProcessMessages(resp); } } } catch (WebException e) { string errorMessage = e.Response != null ? e.Response.Headers["X-Error"] : null; if (!string.IsNullOrEmpty(errorMessage)) { Interaction.Instance.ReportMessage(Path.GetFileName(f) + ": Upload failed: " + errorMessage, ReportType.Fail); } else { Interaction.Instance.ReportMessage(Path.GetFileName(f) + ": Upload failed: " + e.Message, ReportType.Fail); } } } Interaction.Instance.TaskComplete(); }
private async void LoadIrd(string filename) { IrdFile irdFile = await TaskEx.Run(() => IrdFile.Load(filename)); lblVersion.Text = irdFile.Version.ToString(CultureInfo.InvariantCulture); lblUpdateVersion.Text = irdFile.UpdateVersion; lblGameId.Text = irdFile.GameID; lblGameName.Text = irdFile.GameName; lblGameVersion.Text = irdFile.GameVersion; lblAppVersion.Text = irdFile.AppVersion; lblAmountOfRegions.Text = irdFile.RegionHashes.Count.ToString(CultureInfo.InvariantCulture); Region[] regions = await TaskEx.Run(() => irdFile.Header.GetRegions()); for (int i = 0; i < irdFile.RegionHashes.Count && i < regions.Length; i++) { ListViewItem itm = new ListViewItem(i.ToString(CultureInfo.InvariantCulture)); itm.SubItems.Add(regions[i].Start.ToString("X2")); itm.SubItems.Add(regions[i].End.ToString("X2")); itm.SubItems.Add(irdFile.RegionHashes[i].AsString()); lvHashes.Items.Add(itm); } lblData1.Text = irdFile.Data1.AsString(); lblData2.Text = irdFile.Data2.AsString(); picHex.Stream = new MemoryStream(irdFile.PIC); // Shouldn't I dispose this one? d2 = irdFile.Data2; lblHeaderLength.Text = (irdFile.Header.Length / Utilities.SectorSize).ToString(CultureInfo.InvariantCulture); lblFooterLength.Text = (irdFile.Footer.Length / Utilities.SectorSize).ToString(CultureInfo.InvariantCulture); headerHex.Stream = irdFile.Header; footerHex.Stream = irdFile.Footer; lblCrc.Text = BitConverter.GetBytes(irdFile.Crc).AsString(); lblIRDHash.Text = IrdFile.GetHash(irdFile.FullPath); tabCtrl.Visible = true; pbLoading.Visible = false; lvFiles.BeginUpdate(); // Load files PS3CDReader cdReader = await TaskEx.Run(() => new PS3CDReader(irdFile.Header)); foreach (var dmi in cdReader.Members.Where(d => d.IsFile).Distinct()) { ListViewItem itm = new ListViewItem(dmi.Path); KeyValuePair <long, byte[]> h = irdFile.FileHashes.FirstOrDefault(f => f.Key == dmi.StartSector); itm.SubItems.Add(dmi.StartSector.ToString("X2")); itm.SubItems.Add(dmi.Length.ToString("X2")); itm.SubItems.Add(h.Value.AsString()); lvFiles.Items.Add(itm); } lvFiles.EndUpdate(); lblLoadingFiles.Visible = pbLoadingFiles.Visible = false; lvFiles.Visible = true; }
public async Task <bool> DoWork(Stream inputStream, Stream outputStream, CancellationToken cancellation, bool isBuilding = false, IrdFile irdFile = null) { bool retval = true; if ((IsDecrypting && !Interaction.Instance.Compress && inputStream.CanSeek) || (!IsDecrypting && inputStream.CanSeek)) { long length = !isBuilding || irdFile == null ? inputStream.Length : (Regions.Last().End + 1) * Utilities.SectorSize + irdFile.Footer.Length; outputStream.SetLength(length); } for (UInt32 i = 0; !cancellation.IsCancellationRequested && i < (NumPlainRegions * 2) - 1; i++) { Interaction.Instance.ReportMessage( string.Format("Processing {3} region {0} ({1:X2}-{2:X2})", i, Regions[i].Start, Regions[i].End, Regions[i].Type)); await Regions[i].CopyRegion(cancellation, inputStream, outputStream) .ConfigureAwait(false); if (cancellation.IsCancellationRequested) { return(false); } if (!isBuilding) { continue; } if (irdFile != null) { bool match = Regions[i].DestinationHash.AsString() == irdFile.RegionHashes[(int)i].AsString(); if (match) { Interaction.Instance.ReportMessage("Region hash VALID: " + Regions[i].DestinationHash.AsString(), ReportType.Success); } else { retval = false; Interaction.Instance.ReportMessage( "Region hash INVALID. Found: " + Regions[i].DestinationHash.AsString() + ", expected: " + irdFile.RegionHashes[(int)i].AsString(), ReportType.Fail); } } else { Interaction.Instance.ReportMessage("Region " + i + " hash: " + Regions[i].DestinationHash.AsString()); } } return(retval); }
public static IrdFile Load(string path) { Exception ex = null; bool update_ird_file = false; IrdFile ird = new IrdFile(); try { ird.FullPath = path; using (Stream s = Open(path)) { using (CrcCalculatorStream crc = new CrcCalculatorStream(s, true)) { using (BinaryReader br = new BinaryReader(crc)) { // Read magic byte[] magic = br.ReadBytes(4); if (magic.AsString() != MAGIC.AsString()) { ex = new FileLoadException("Invalid IRD file", path); throw ex; } // Read version ird.Version = br.ReadByte(); if (ird.Version != IrdVersion) { if (!CompatibleVersions.Any(v => v == ird.Version)) { ex = new FileLoadException("Unsupported IRD file version (Found version " + ird.Version + ")", path); throw ex; } update_ird_file = true; } ird.gameId = Encoding.ASCII.GetString(br.ReadBytes(9)).Trim('\0'); ird.GameName = br.ReadString(); // Read version of update file byte[] update = br.ReadBytes(4); ird.UpdateVersion = Encoding.ASCII.GetString(update).Trim('\0'); // Read the gameversion byte[] gameVersion = br.ReadBytes(5); ird.GameVersion = Encoding.ASCII.GetString(gameVersion).Trim('\0'); byte[] appVersion = br.ReadBytes(5); ird.AppVersion = Encoding.ASCII.GetString(appVersion).Trim('\0'); // Read header and footer sectors ird.Header = br.Uncompress(); ird.Footer = br.Uncompress(); // Read region hashes int amountOfHashes = br.ReadByte(); for (int i = 0; i < amountOfHashes; i++) { byte[] hash = br.ReadBytes(0x10); ird.RegionHashes.Add(hash); } // Read file hashes int amountOfFiles = br.ReadInt32(); ird.FileHashes = new Dictionary <long, byte[]>(amountOfFiles); for (int i = 0; i < amountOfFiles; i++) { long sector = br.ReadInt64(); byte[] hash = br.ReadBytes(0x10); ird.FileHashes.Add(sector, hash); } // Read amount of attachments and extra config fields int extraConfig = br.ReadUInt16(); int attachments = br.ReadUInt16(); // Yes, we don't use these for now, but we might in the future ird.Data1 = br.ReadBytes(0x10); ird.Data2 = br.ReadBytes(0x10); ird.PIC = br.ReadBytes(0x73); } ird.Crc = (uint)crc.Crc; } byte[] crcValue = new byte[4]; s.Read(crcValue, 0, 4); if (ird.Crc != BitConverter.ToUInt32(crcValue, 0)) { ex = new FileLoadException("Invalid CRC value in the IRD file", path); throw ex; } } if (update_ird_file) { Interaction.Instance.ReportMessage("Updating IRD file to latest version: " + Path.GetFileName(path)); ird.Save(path); } return(ird); } catch (ZlibException) { // Annoying bug in the zlib decompression of Ionic.Zip if (ex != null) { throw ex; } return(ird); } catch (EndOfStreamException e) { throw new FileLoadException("Unexpected end of IRD file", path, e); } }