Ejemplo n.º 1
0
        /// <summary>
        /// Generate a list of DatItem objects from the header values in an archive
        /// </summary>
        /// <param name="omitFromScan">Hash representing the hashes that should be skipped</param>
        /// <param name="date">True if entry dates should be included, false otherwise (default)</param>
        /// <returns>List of DatItem objects representing the found data</returns>
        /// <remarks>TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually</remarks>
        public override List <BaseFile> GetChildren(Hash omitFromScan = Hash.DeepHashes, bool date = false)
        {
            List <BaseFile> found    = new List <BaseFile>();
            string          gamename = Path.GetFileNameWithoutExtension(_filename);

            try
            {
                ZipFile   zf = new ZipFile();
                ZipReturn zr = zf.Open(_filename, new FileInfo(_filename).LastWriteTime.Ticks, true);
                if (zr != ZipReturn.ZipGood)
                {
                    throw new Exception(ZipFile.ZipErrorMessageText(zr));
                }

                for (int i = 0; i < zf.EntriesCount; i++)
                {
                    // Open the read stream
                    zr = zf.OpenReadStream(i, false, out Stream readStream, out ulong streamsize, out SabreTools.Library.Data.CompressionMethod cm, out uint lastMod);

                    // If we get a read error, log it and continue
                    if (zr != ZipReturn.ZipGood)
                    {
                        Globals.Logger.Warning("An error occurred while reading archive {0}: Zip Error - {1}", _filename, zr);
                        continue;
                    }

                    // If the entry ends with a directory separator, continue to the next item, if any
                    if (zf.Entries[i].FileName.EndsWith(Path.DirectorySeparatorChar.ToString()) ||
                        zf.Entries[i].FileName.EndsWith(Path.AltDirectorySeparatorChar.ToString()) ||
                        zf.Entries[i].FileName.EndsWith(Path.PathSeparator.ToString()))
                    {
                        continue;
                    }

                    // If secure hashes are disabled, do a quickscan
                    if (omitFromScan == Hash.SecureHashes)
                    {
                        string newname       = zf.Entries[i].FileName;
                        long   newsize       = (long)zf.Entries[i].UncompressedSize;
                        byte[] newcrc        = zf.Entries[i].CRC.Reverse().ToArray();
                        string convertedDate = Utilities.ConvertMsDosTimeFormatToDateTime(zf.Entries[i].LastMod).ToString("yyyy/MM/dd hh:mm:ss");

                        found.Add(new BaseFile
                        {
                            Filename = newname,
                            Size     = newsize,
                            CRC      = newcrc,
                            Date     = (date ? convertedDate : null),

                            Parent = gamename,
                        });
                    }
                    // Otherwise, use the stream directly
                    else
                    {
                        BaseFile zipEntryRom = Utilities.GetStreamInfo(readStream, (long)zf.Entries[i].UncompressedSize, omitFromScan: omitFromScan, keepReadOpen: true);
                        zipEntryRom.Filename = zf.Entries[i].FileName;
                        zipEntryRom.Parent   = gamename;
                        string convertedDate = Utilities.ConvertMsDosTimeFormatToDateTime(zf.Entries[i].LastMod).ToString("yyyy/MM/dd hh:mm:ss");
                        zipEntryRom.Date = (date ? convertedDate : null);
                        found.Add(zipEntryRom);
                    }
                }

                // Dispose of the archive
                zr = zf.CloseReadStream();
                zf.Close();
            }
            catch (Exception ex)
            {
                Globals.Logger.Error(ex.ToString());
                return(null);
            }

            return(found);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Attempt to extract a file as an archive
        /// </summary>
        /// <param name="outDir">Output directory for archive extraction</param>
        /// <returns>True if the extraction was a success, false otherwise</returns>
        public override bool CopyAll(string outDir)
        {
            bool encounteredErrors = true;

            try
            {
                // Create the temp directory
                Directory.CreateDirectory(outDir);

                // Extract all files to the temp directory
                ZipFile   zf = new ZipFile();
                ZipReturn zr = zf.Open(_filename, new FileInfo(_filename).LastWriteTime.Ticks, true);
                if (zr != ZipReturn.ZipGood)
                {
                    throw new Exception(ZipFile.ZipErrorMessageText(zr));
                }

                for (int i = 0; i < zf.EntriesCount && zr == ZipReturn.ZipGood; i++)
                {
                    // Open the read stream
                    zr = zf.OpenReadStream(i, false, out Stream readStream, out ulong streamsize, out SabreTools.Library.Data.CompressionMethod cm, out uint lastMod);

                    // Create the rest of the path, if needed
                    if (!String.IsNullOrWhiteSpace(Path.GetDirectoryName(zf.Entries[i].FileName)))
                    {
                        Directory.CreateDirectory(Path.Combine(outDir, Path.GetDirectoryName(zf.Entries[i].FileName)));
                    }

                    // If the entry ends with a directory separator, continue to the next item, if any
                    if (zf.Entries[i].FileName.EndsWith(Path.DirectorySeparatorChar.ToString()) ||
                        zf.Entries[i].FileName.EndsWith(Path.AltDirectorySeparatorChar.ToString()) ||
                        zf.Entries[i].FileName.EndsWith(Path.PathSeparator.ToString()))
                    {
                        continue;
                    }

                    FileStream writeStream = Utilities.TryCreate(Path.Combine(outDir, zf.Entries[i].FileName));

                    // If the stream is smaller than the buffer, just run one loop through to avoid issues
                    if (streamsize < _bufferSize)
                    {
                        byte[] ibuffer = new byte[streamsize];
                        int    ilen    = readStream.Read(ibuffer, 0, (int)streamsize);
                        writeStream.Write(ibuffer, 0, ilen);
                        writeStream.Flush();
                    }
                    // Otherwise, we do the normal loop
                    else
                    {
                        int    realBufferSize = (streamsize < _bufferSize ? (int)streamsize : _bufferSize);
                        byte[] ibuffer        = new byte[realBufferSize];
                        int    ilen;
                        while ((ilen = readStream.Read(ibuffer, 0, realBufferSize)) > 0)
                        {
                            writeStream.Write(ibuffer, 0, ilen);
                            writeStream.Flush();
                        }
                    }

                    zr = zf.CloseReadStream();
                    writeStream.Dispose();
                }
                zf.Close();
                encounteredErrors = false;
            }
            catch (EndOfStreamException)
            {
                // Catch this but don't count it as an error because SharpCompress is unsafe
            }
            catch (InvalidOperationException)
            {
                encounteredErrors = true;
            }
            catch (Exception ex)
            {
                Globals.Logger.Error(ex.ToString());
                encounteredErrors = true;
            }

            return(encounteredErrors);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Attempt to extract a stream from an archive
        /// </summary>
        /// <param name="entryName">Name of the entry to be extracted</param>
        /// <param name="realEntry">Output representing the entry name that was found</param>
        /// <returns>MemoryStream representing the entry, null on error</returns>
        public override (MemoryStream, string) CopyToStream(string entryName)
        {
            MemoryStream ms        = new MemoryStream();
            string       realEntry = null;

            try
            {
                ZipFile   zf = new ZipFile();
                ZipReturn zr = zf.Open(_filename, new FileInfo(_filename).LastWriteTime.Ticks, true);
                if (zr != ZipReturn.ZipGood)
                {
                    throw new Exception(ZipFile.ZipErrorMessageText(zr));
                }

                for (int i = 0; i < zf.EntriesCount && zr == ZipReturn.ZipGood; i++)
                {
                    if (zf.Entries[i].FileName.Contains(entryName))
                    {
                        // Open the read stream
                        realEntry = zf.Entries[i].FileName;
                        zr        = zf.OpenReadStream(i, false, out Stream readStream, out ulong streamsize, out SabreTools.Library.Data.CompressionMethod cm, out uint lastMod);

                        // If the stream is smaller than the buffer, just run one loop through to avoid issues
                        if (streamsize < _bufferSize)
                        {
                            byte[] ibuffer = new byte[streamsize];
                            int    ilen    = readStream.Read(ibuffer, 0, (int)streamsize);
                            ms.Write(ibuffer, 0, ilen);
                            ms.Flush();
                        }
                        // Otherwise, we do the normal loop
                        else
                        {
                            byte[] ibuffer = new byte[_bufferSize];
                            int    ilen;
                            while (streamsize > _bufferSize)
                            {
                                ilen = readStream.Read(ibuffer, 0, _bufferSize);
                                ms.Write(ibuffer, 0, ilen);
                                ms.Flush();
                                streamsize -= _bufferSize;
                            }

                            ilen = readStream.Read(ibuffer, 0, (int)streamsize);
                            ms.Write(ibuffer, 0, ilen);
                            ms.Flush();
                        }

                        zr = zf.CloseReadStream();
                    }
                }

                zf.Dispose();
            }
            catch (Exception ex)
            {
                Globals.Logger.Error(ex.ToString());
                ms        = null;
                realEntry = null;
            }

            return(ms, realEntry);
        }