Пример #1
0
        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);
            }
        }
Пример #2
0
        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();
        }
Пример #3
0
        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;
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
            }
        }