示例#1
0
        public static void WriteRLEHeader(Stream stream, MetaIWriteList data)
        {
            byte[]       headerBuf = new byte[HeaderSize(data.Count)];
            BinaryWriter writer    = new BinaryWriter(new MemoryStream(headerBuf));

            writer.Write(ppVersionBytes);
            writer.Write(DecryptHeaderBytes(BitConverter.GetBytes(Version)));

            writer.Write(DecryptHeaderBytes(new byte[] { FirstByte }));
            writer.Write(DecryptHeaderBytes(BitConverter.GetBytes(data.Count)));

            List <uint> offsets = new List <uint>();

            byte[] fileHeaderBuf = new byte[288 * data.Count];
            uint   fileOffset    = (uint)headerBuf.Length;

            for (int i = 0; i < data.Count; i++)
            {
                IWriteFile subfile  = data[i].WriteFile;
                uint       hash     = data[i].Hash;
                uint       size     = data[i].Size;
                object     metadata = data[i].Metadata;

                bool collision = data.GetRange(0, i)
                                 .Any(x => x.Hash == hash);

                uint currentOffset = fileOffset;

                if (collision)
                {
                    int index = data.IndexOf(data.GetRange(0, i)
                                             .First(x => x.Hash == hash));

                    size = data[index].Size;

                    currentOffset = offsets[index];
                }

                offsets.Add(currentOffset);

                int idx = i * 288;
                Utility.EncodingShiftJIS.GetBytes(subfile.Name).CopyTo(fileHeaderBuf, idx);
                BitConverter.GetBytes(size).CopyTo(fileHeaderBuf, idx + 260);
                BitConverter.GetBytes(currentOffset).CopyTo(fileHeaderBuf, idx + 264);

                Metadata wakeariMetadata = (Metadata)metadata;
                System.Array.Copy(wakeariMetadata.LastBytes, 0, fileHeaderBuf, idx + 268, 20);
                BitConverter.GetBytes(size).CopyTo(fileHeaderBuf, idx + 284);

                if (!collision)
                {
                    fileOffset += size;
                }
            }

            writer.Write(DecryptHeaderBytes(fileHeaderBuf));
            writer.Write(DecryptHeaderBytes(BitConverter.GetBytes(headerBuf.Length)));
            writer.Flush();
            stream.Write(headerBuf, 0, headerBuf.Length);
        }
示例#2
0
        void writeArchiveWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;
            string           backup = null;

            string dirName = Path.GetDirectoryName(destPath);

            if (dirName == String.Empty)
            {
                dirName = @".\";
            }
            DirectoryInfo dir = new DirectoryInfo(dirName);

            if (!dir.Exists)
            {
                dir.Create();
            }

            if (File.Exists(destPath))
            {
                backup = Utility.GetDestFile(dir, Path.GetFileNameWithoutExtension(destPath), ".bak");
                File.Move(destPath, backup);

                if (destPath.Equals(this.FilePath, StringComparison.InvariantCultureIgnoreCase))
                {
                    foreach (IWriteFile iw in Subfiles)
                    {
                        if (iw is ppSubfile)
                        {
                            ppSubfile subfile = iw as ppSubfile;
                            if (subfile.ppPath.Equals(this.FilePath, StringComparison.InvariantCultureIgnoreCase))
                            {
                                subfile.ppPath = backup;
                            }
                        }
                    }
                }
            }

            try
            {
                using (BinaryWriter writer = new BinaryWriter(File.Create(destPath)))
                {
                    writer.BaseStream.Seek(ppHeader.HeaderSize(Subfiles.Count), SeekOrigin.Begin);
                    long offset = writer.BaseStream.Position;
                    var  Hashes = new MetaIWriteList();

                    for (int i = 0; i < Subfiles.Count; i++)
                    {
                        if (worker.CancellationPending)
                        {
                            e.Cancel = true;
                            break;
                        }

                        worker.ReportProgress(i * 100 / Subfiles.Count);

                        System.Diagnostics.Trace.WriteLine(Subfiles[i].Name);

                        if (Subfiles[i] is ppSubfile)
                        {
                            ppSubfile subfile = Subfiles[i] as ppSubfile;
                            using (MD5 md5 = MD5.Create())
                                using (MemoryStream mem = new MemoryStream())
                                    using (BinaryReader reader = new BinaryReader(File.OpenRead(subfile.ppPath)))
                                    {
                                        reader.BaseStream.Seek(subfile.offset, SeekOrigin.Begin);
                                        int bufsize = Utility.EstBufSize(subfile.size);

                                        uint hash = 0;

                                        if (bufsize == 0)
                                        {
                                            Hashes.AddNew(Subfiles[i], hash, 0, subfile.Metadata);
                                            continue;
                                        }

                                        int readSteps = (int)subfile.size / bufsize;

                                        byte[] buf;

                                        for (int j = 0; j < readSteps; j++)
                                        {
                                            buf = reader.ReadBytes(bufsize);

                                            md5.TransformBlock(buf, 0, bufsize, buf, 0);

                                            mem.WriteBytes(buf);
                                        }
                                        int remaining = (int)(subfile.size % bufsize);

                                        buf = reader.ReadBytes(remaining);
                                        md5.TransformFinalBlock(buf, 0, remaining);
                                        mem.WriteBytes(buf);

                                        hash = BitConverter.ToUInt32(md5.Hash, 0);

                                        if (!Hashes.Any(x => x.Hash == hash))
                                        {
                                            writer.Write(mem.ToArray());

                                            Hashes.AddNew(Subfiles[i], hash, (uint)(writer.BaseStream.Position - offset), subfile.Metadata);
                                        }
                                        else
                                        {
                                            var first = Hashes.First(x => x.Hash == hash);

                                            Hashes.AddNew(Subfiles[i], hash, first.Size, first.Metadata);
                                        }
                                    }
                        }
                        else
                        {
                            Stream stream = ppFormat.WriteStream(writer.BaseStream);

                            using (MD5 md5 = MD5.Create())
                                using (MemoryStream mem = new MemoryStream())
                                {
                                    Subfiles[i].WriteTo(mem);

                                    uint hash = BitConverter.ToUInt32(md5.ComputeHash(mem.ToArray()), 0);

                                    if (Hashes.Any(x => x.Hash == hash))
                                    {
                                        var first = Hashes.First(x => x.Hash == hash);
                                        Hashes.AddNew(Subfiles[i], hash, first.Size, first.Metadata);
                                    }
                                    else
                                    {
                                        mem.WriteTo(stream);
                                        object meta = ppFormat.FinishWriteTo(stream);
                                        long   ppos = writer.BaseStream.Position;

                                        Hashes.AddNew(Subfiles[i], hash, (uint)(ppos - offset), meta);
                                    }
                                }
                        }
                        offset = writer.BaseStream.Position;
                    }

                    if (!e.Cancel)
                    {
                        writer.BaseStream.Seek(0, SeekOrigin.Begin);

                        ppHeader.WriteRLEHeader(writer.BaseStream, Hashes);
                    }
                }

                if (e.Cancel)
                {
                    RestoreBackup(destPath, backup);
                }
                else if ((backup != null) && !keepBackup)
                {
                    File.Delete(backup);
                }

                foreach (IWriteFile iw in Subfiles)
                {
                    if (iw is IDisposable)
                    {
                        ((IDisposable)iw).Dispose();
                    }
                }

                //ReloadSubfiles();
            }
            catch (Exception ex)
            {
                RestoreBackup(destPath, backup);
                throw new Exception("PP Parser has encountered an error.", ex);
            }
        }