Beispiel #1
0
        public static async Task GetMetaData()
        {
            List <Task> tlist = new List <Task>();

            vehicles.ForEach(a =>
            {
                try
                {
                    var newurl = String.Format(url, a);
                    var file   = Path.Combine(Settings.GetDataDirectory(), "LogMessages" + a + ".xml.xz");
                    if (File.Exists(file))
                    {
                        if (new FileInfo(file).LastWriteTime.AddDays(7) > DateTime.Now)
                        {
                            return;
                        }
                    }
                    var dltask = Download.getFilefromNetAsync(newurl, file);
                    tlist.Add(dltask);
                }
                catch (Exception ex) { log.Error(ex); }
            });

            await Task.WhenAll(tlist);

            vehicles.ForEach(a =>
            {
                try
                {
                    var fileout = Path.Combine(Settings.GetDataDirectory(), "LogMessages" + a + ".xml");
                    var file    = Path.Combine(Settings.GetDataDirectory(), "LogMessages" + a + ".xml.xz");
                    if (File.Exists(file))
                    {
                        using (var read = File.OpenRead(file))
                        {
                            if (XZStream.IsXZStream(read))
                            {
                                read.Position = 0;
                                var stream    = new XZStream(read);
                                using (var outst = File.OpenWrite(fileout))
                                {
                                    try
                                    {
                                        stream.CopyTo(outst);
                                    }
                                    catch (XZIndexMarkerReachedException)
                                    {
                                        // ignore
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }
            });
        }
Beispiel #2
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;

            try
            {
                // Decompress the _filename stream
                realEntry = Path.GetFileNameWithoutExtension(this.Filename);
                var xz = new XZStream(File.OpenRead(this.Filename));

                // Write the file out
                byte[] xbuffer = new byte[_bufferSize];
                int    xlen;
                while ((xlen = xz.Read(xbuffer, 0, _bufferSize)) > 0)
                {
                    ms.Write(xbuffer, 0, xlen);
                    ms.Flush();
                }

                // Dispose of the streams
                xz.Dispose();
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                ms        = null;
                realEntry = null;
            }

            return(ms, realEntry);
        }
 /// Main function that decompresses a xz file and serialized it 
 // into a json for mongodb storage.
 public static void Main(string[] args)
 {
     if (args.Length != 1)
     {
         Console.Write("syntax is ./FundUniquePackages.exe <file>.xz");
         return;
     }
     var fs = File.OpenRead(args[0]);
     if (fs.Name.EndsWith(".xz"))
     {
         using (Stream zipStream = new XZStream(fs))
         {
             using (StreamReader unzip = new StreamReader(zipStream))
             {
                 while (!unzip.EndOfStream)
                 {
                     streamReadHelper(unzip);
                 }
             }
         }
     } else {
         using (StreamReader fsStream = new StreamReader(fs))
         {
             while (!fsStream.EndOfStream)
             {
                 streamReadHelper(fsStream);
             }
         }
     }
     File.WriteAllText("FileSystemBinaries.json", JsonConvert.SerializeObject(serializationTransform(filesystemToBinaryInfo)));
     File.WriteAllText("BinaryVariations.json", JsonConvert.SerializeObject(serializationTransform(binaryNameToBinaryInfo)));
     //File.WriteAllText("SimilarityArray.json", generateSimilarityMatrix());
 }
        private static void Template(string xzFileName, string originFileName, bool useSpan)
        {
            byte[] decompDigest;
            byte[] originDigest;

            string xzFile     = Path.Combine(TestSetup.SampleDir, xzFileName);
            string originFile = Path.Combine(TestSetup.SampleDir, originFileName);

            using (MemoryStream decompMs = new MemoryStream())
            {
                XZDecompressOptions decompOpts = new XZDecompressOptions();

                using (FileStream compFs = new FileStream(xzFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                    using (XZStream xz = new XZStream(compFs, decompOpts))
                    {
#if !NETFRAMEWORK
                        if (useSpan)
                        {
                            byte[] buffer = new byte[64 * 1024];

                            int bytesRead;
                            do
                            {
                                bytesRead = xz.Read(buffer.AsSpan());
                                decompMs.Write(buffer.AsSpan(0, bytesRead));
                            } while (0 < bytesRead);
                        }
                        else
#endif
                        {
                            xz.CopyTo(decompMs);
                        }

                        decompMs.Flush();
                        xz.GetProgress(out ulong finalIn, out ulong finalOut);

                        Assert.AreEqual(compFs.Length, xz.TotalIn);
                        Assert.AreEqual(decompMs.Length, xz.TotalOut);
                        Assert.AreEqual((ulong)compFs.Length, finalIn);
                        Assert.AreEqual((ulong)decompMs.Length, finalOut);
                    }
                decompMs.Position = 0;

                using (HashAlgorithm hash = SHA256.Create())
                {
                    decompDigest = hash.ComputeHash(decompMs);
                }
            }

            using (FileStream originFs = new FileStream(originFile, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (HashAlgorithm hash = SHA256.Create())
                {
                    originDigest = hash.ComputeHash(originFs);
                }
            }

            Assert.IsTrue(decompDigest.SequenceEqual(originDigest));
        }
Beispiel #5
0
 public void CanReadStream()
 {
     XZStream xz = new XZStream(CompressedStream);
     using (var sr = new StreamReader(xz))
     {
         string uncompressed = sr.ReadToEnd();
         Assert.That(uncompressed, Is.EqualTo(Original));
     }
 }
Beispiel #6
0
        /// <summary>
        /// Generate a list of DatItem objects from the header values in an archive
        /// </summary>
        /// <returns>List of DatItem objects representing the found data</returns>
        public override List <BaseFile> GetChildren()
        {
            if (_children == null || _children.Count == 0)
            {
                _children = new List <BaseFile>();

                string gamename = Path.GetFileNameWithoutExtension(this.Filename);

                BaseFile possibleTxz = GetTorrentXZFileInfo();

                // If it was, then add it to the outputs and continue
                if (possibleTxz != null && possibleTxz.Filename != null)
                {
                    _children.Add(possibleTxz);
                }
                else
                {
                    try
                    {
                        // Create a blank item for the entry
                        BaseFile xzEntryRom = new BaseFile();

                        // Perform a quickscan, if flagged to
                        if (this.AvailableHashes == Hash.CRC)
                        {
                            xzEntryRom.Filename = gamename;
                            using (BinaryReader br = new BinaryReader(FileExtensions.TryOpenRead(this.Filename)))
                            {
                                br.BaseStream.Seek(-8, SeekOrigin.End);
                                xzEntryRom.CRC  = br.ReadBytesBigEndian(4);
                                xzEntryRom.Size = br.ReadInt32BigEndian();
                            }
                        }
                        // Otherwise, use the stream directly
                        else
                        {
                            var xzStream = new XZStream(File.OpenRead(this.Filename));
                            xzEntryRom          = xzStream.GetInfo(hashes: this.AvailableHashes);
                            xzEntryRom.Filename = gamename;
                            xzStream.Dispose();
                        }

                        // Fill in comon details and add to the list
                        xzEntryRom.Parent = gamename;
                        _children.Add(xzEntryRom);
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex);
                        return(null);
                    }
                }
            }

            return(_children);
        }
Beispiel #7
0
        public void CanReadStream()
        {
            XZStream xz = new XZStream(CompressedStream);

            using (var sr = new StreamReader(xz))
            {
                string uncompressed = sr.ReadToEnd();
                Assert.Equal(uncompressed, Original);
            }
        }
Beispiel #8
0
        public void NativeXZ()
        {
            byte[] buffer = _srcFileBytesDict[DecompMethod.NativeXZ];

            using (MemoryStream decompMs = new MemoryStream((int)_magicFileLen))
                using (MemoryStream compMs = new MemoryStream(buffer))
                    using (XZStream xzs = new XZStream(compMs, new XZDecompressOptions()))
                    {
                        xzs.CopyTo(decompMs);
                    }
        }
Beispiel #9
0
        public override byte[] Decompress(byte[] compressedData)
        {
            var inStream  = new MemoryStream(compressedData);
            var outStream = new MemoryStream();

            using (var decompress = new XZStream(inStream))
            {
                CopyTo(decompress, outStream);
            }
            return(outStream.ToArray());
        }
Beispiel #10
0
        /// <inheritdoc/>
        public override byte[] Decompress(byte[] compressedData, int blockLength)
        {
            XZDecompressOptions decompOpts = new XZDecompressOptions();

            using (MemoryStream inputStream = new MemoryStream(compressedData, 0, blockLength))
                using (MemoryStream outputStream = new MemoryStream())
                    using (XZStream xzStream = new XZStream(inputStream, decompOpts))
                    {
                        xzStream.CopyTo(outputStream);
                        xzStream.Flush();
                        return(outputStream.ToArray());
                    }
        }
        /// <summary>
        ///     Extracts an zip file contained in fileEntry.
        /// </summary>
        /// <param name="fileEntry"> FileEntry to extract </param>
        /// <returns> Extracted files </returns>
        public IEnumerable <FileEntry> Extract(FileEntry fileEntry, ExtractorOptions options, ResourceGovernor governor)
        {
            XZStream?xzStream = null;

            try
            {
                xzStream = new XZStream(fileEntry.Content);
            }
            catch (Exception e)
            {
                Logger.Debug(Extractor.DEBUG_STRING, ArchiveFileType.XZ, fileEntry.FullPath, string.Empty, e.GetType());
            }
            if (xzStream != null)
            {
                var newFilename  = Path.GetFileNameWithoutExtension(fileEntry.Name);
                var newFileEntry = new FileEntry(newFilename, xzStream, fileEntry);

                // SharpCompress does not expose metadata without a full read, so we need to decompress first,
                // and then abort if the bytes exceeded the governor's capacity.

                var streamLength = xzStream.Index?.Records?.Select(r => r.UncompressedSize)
                                   .Aggregate((ulong?)0, (a, b) => a + b);

                // BUG: Technically, we're casting a ulong to a long, but we don't expect 9 exabyte steams, so
                // low risk.
                if (streamLength.HasValue)
                {
                    governor.CheckResourceGovernor((long)streamLength.Value);
                }

                if (Extractor.IsQuine(newFileEntry))
                {
                    Logger.Info(Extractor.IS_QUINE_STRING, fileEntry.Name, fileEntry.FullPath);
                    throw new OverflowException();
                }

                foreach (var extractedFile in Context.Extract(newFileEntry, options, governor))
                {
                    yield return(extractedFile);
                }
                xzStream.Dispose();
            }
            else
            {
                if (options.ExtractSelfOnFail)
                {
                    yield return(fileEntry);
                }
            }
        }
Beispiel #12
0
        public static string DecompressXZFile(string sourceFilePath, string destinationDirectory, TaskLoggingHelper logger)
        {
            var destFile = Path.Combine(destinationDirectory, Path.GetFileName(sourceFilePath)) + ".uncompressed";

            if (File.Exists(destFile))
            {
                LogMessage($"Uncompressed tar file already exists: {destFile}", logger);
                return(destFile);
            }

            using (Stream xz = new XZStream(File.OpenRead(sourceFilePath)))
                using (Stream outputStream = new FileStream(destFile, FileMode.CreateNew))
                {
                    xz.CopyTo(outputStream);
                }
            return(destFile);
        }
Beispiel #13
0
        /// <summary>
        /// Write an input file to a torrent XZ archive
        /// </summary>
        /// <param name="inputStream">Input stream to be moved</param>
        /// <param name="outDir">Output directory to build to</param>
        /// <param name="rom">DatItem representing the new information</param>
        /// <returns>True if the archive was written properly, false otherwise</returns>
        public override bool Write(Stream inputStream, string outDir, Rom rom)
        {
            bool success = false;

            // If the stream is not readable, return
            if (!inputStream.CanRead)
            {
                return(success);
            }

            // Make sure the output directory exists
            if (!Directory.Exists(outDir))
            {
                Directory.CreateDirectory(outDir);
            }

            outDir = Path.GetFullPath(outDir);

            // Now get the Rom info for the file so we have hashes and size
            rom = new Rom(inputStream.GetInfo(keepReadOpen: true));

            // Get the output file name
            string outfile = Path.Combine(outDir, PathExtensions.GetDepotPath(rom.SHA1, Depth));

            outfile = outfile.Replace(".gz", ".xz");

            // Check to see if the folder needs to be created
            if (!Directory.Exists(Path.GetDirectoryName(outfile)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(outfile));
            }

            // If the output file exists, don't try to write again
            if (!File.Exists(outfile))
            {
                // Compress the input stream
                XZStream outputStream = new XZStream(FileExtensions.TryCreate(outfile));
                inputStream.CopyTo(outputStream);

                // Dispose of everything
                outputStream.Dispose();
            }

            return(true);
        }
Beispiel #14
0
        private static (bool, string?) ExtractLinux(FileInfo archiveFile, string destination)
        {
            using var stream = archiveFile.OpenRead();
            bool isXz = XZStream.IsXZStream(stream);

            stream.Position = 0;
            if (isXz)
            {
                using var xzStream = new XZStream(stream);
                using var reader   = TarReader.Open(xzStream);
                return(Extract(reader, destination));
            }
            else
            {
                using var reader = TarReader.Open(stream);
                return(Extract(reader, destination));
            }
        }
Beispiel #15
0
        private static async Task ReadTarXzAsync(
            FileStream fileStream,
            string outputDir,
            Func <string, string> getEntryPath,
            bool shouldExtract)
        {
            using (var xzStream = new XZStream(fileStream))
                using (var tarReader = TarReader.Open(xzStream))
                {
                    var createdDirs = new HashSet <string>();

                    while (tarReader.MoveToNextEntry())
                    {
                        if (!shouldExtract)
                        {
                            return;
                        }

                        if (tarReader.Entry.IsDirectory)
                        {
                            continue;
                        }

                        var entryPath = getEntryPath(tarReader.Entry.Key);
                        if (entryPath == null)
                        {
                            continue;
                        }

                        var fullEntryPath = Path.GetFullPath(Path.Combine(outputDir, entryPath));
                        var entryDir      = Path.GetDirectoryName(fullEntryPath);
                        if (createdDirs.Add(entryDir))
                        {
                            Directory.CreateDirectory(entryDir);
                        }

                        using (var entryStream = tarReader.OpenEntryStream())
                            using (var outputStream = new FileStream(fullEntryPath, FileMode.Create))
                            {
                                await entryStream.CopyToAsync(outputStream).ConfigureAwait(false);
                            }
                    }
                }
        }
Beispiel #16
0
 public int OnExecute(IConsole console)
 {
     try
     {
         using (var istm = Util.OpenInputStream(InputFile))
             using (var ostm = Util.OpenOutputStream(OutputFile, true))
             {
                 using (var izstm = new XZStream(istm))
                 {
                     izstm.CopyTo(ostm);
                 }
             }
     }
     catch (Exception e)
     {
         console.Error.WriteLine($"failed xz decompression:{e}");
         return(1);
     }
     return(0);
 }
Beispiel #17
0
        /// <inheritdoc/>
        public ConcurrentDictionary <string, ConcurrentQueue <string> > Scan(Scanner scanner, Stream stream, string file)
        {
            // If the xz file itself fails
            try
            {
                string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
                Directory.CreateDirectory(tempPath);

                using (XZStream xzFile = new XZStream(stream))
                {
                    // If an individual entry fails
                    try
                    {
                        string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
                        using (FileStream fs = File.OpenWrite(tempFile))
                        {
                            xzFile.CopyTo(fs);
                        }
                    }
                    catch { }
                }

                // Collect and format all found protections
                var protections = scanner.GetProtections(tempPath);

                // If temp directory cleanup fails
                try
                {
                    Directory.Delete(tempPath, true);
                }
                catch { }

                // Remove temporary path references
                Utilities.StripFromKeys(protections, tempPath);

                return(protections);
            }
            catch { }

            return(null);
        }
Beispiel #18
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);

                // Decompress the _filename stream
                FileStream outstream = FileExtensions.TryCreate(Path.Combine(outDir, Path.GetFileNameWithoutExtension(this.Filename)));
                var        xz        = new XZStream(File.OpenRead(this.Filename));
                xz.CopyTo(outstream);

                // Dispose of the streams
                outstream.Dispose();
                xz.Dispose();

                encounteredErrors = false;
            }
            catch (EndOfStreamException ex)
            {
                // Catch this but don't count it as an error because SharpCompress is unsafe
                logger.Verbose(ex);
            }
            catch (InvalidOperationException ex)
            {
                logger.Warning(ex);
                encounteredErrors = true;
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                encounteredErrors = true;
            }

            return(encounteredErrors);
        }
Beispiel #19
0
        /// <inheritdoc/>
        public override void Compress(MemoryStream inputStream, MemoryStream outputStream)
        {
            XZCompressOptions compOpts = new XZCompressOptions
            {
                Level       = (LzmaCompLevel)(int)Level,
                ExtremeFlag = Extreme,
                LeaveOpen   = true
            };

            XZThreadedCompressOptions threadOpts = new XZThreadedCompressOptions
            {
                Threads = Threads,
            };

            inputStream.Position = 0;
            outputStream.SetLength(0);

            using (XZStream xzStream = new XZStream(outputStream, compOpts, threadOpts))
            {
                inputStream.CopyTo(xzStream);
                xzStream.Flush();
            }
        }
        private static void CompressTemplate(string sampleFileName, bool useSpan, bool success, int threads, LzmaCompLevel level, bool extreme)
        {
            string destDir = Path.GetTempFileName();

            File.Delete(destDir);
            Directory.CreateDirectory(destDir);
            try
            {
                string tempDecompFile = Path.Combine(destDir, Path.GetFileName(sampleFileName));
                string tempXzFile     = tempDecompFile + ".xz";

                XZCompressOptions compOpts = new XZCompressOptions
                {
                    Level       = level,
                    ExtremeFlag = extreme,
                    LeaveOpen   = true,
                };
                XZThreadedCompressOptions threadOpts = new XZThreadedCompressOptions
                {
                    Threads = threads,
                };

                string sampleFile = Path.Combine(TestSetup.SampleDir, sampleFileName);
                using (FileStream xzCompFs = new FileStream(tempXzFile, FileMode.Create, FileAccess.Write, FileShare.None))
                    using (FileStream sampleFs = new FileStream(sampleFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                        using (XZStream xzs = new XZStream(xzCompFs, compOpts, threadOpts))
                        {
#if !NETFRAMEWORK
                            if (useSpan)
                            {
                                byte[] buffer = new byte[64 * 1024];

                                int bytesRead;
                                do
                                {
                                    bytesRead = sampleFs.Read(buffer.AsSpan());
                                    xzs.Write(buffer.AsSpan(0, bytesRead));
                                } while (0 < bytesRead);
                            }
                            else
#endif
                            {
                                sampleFs.CopyTo(xzs);
                            }

                            xzs.Flush();
                            xzs.GetProgress(out ulong finalIn, out ulong finalOut);

                            Assert.AreEqual(sampleFs.Length, xzs.TotalIn);
                            Assert.AreEqual(xzCompFs.Length, xzs.TotalOut);
                            Assert.AreEqual((ulong)sampleFs.Length, finalIn);
                            Assert.AreEqual((ulong)xzCompFs.Length, finalOut);
                        }

                Assert.IsTrue(TestHelper.RunXZ(tempXzFile) == 0);

                byte[] decompDigest;
                byte[] originDigest;
                using (FileStream fs = new FileStream(sampleFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (HashAlgorithm hash = SHA256.Create())
                    {
                        originDigest = hash.ComputeHash(fs);
                    }
                }

                using (FileStream fs = new FileStream(tempDecompFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (HashAlgorithm hash = SHA256.Create())
                    {
                        decompDigest = hash.ComputeHash(fs);
                    }
                }

                Assert.IsTrue(originDigest.SequenceEqual(decompDigest));
                Assert.IsTrue(success);
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception)
            {
                Assert.IsFalse(success);
            }
#pragma warning restore CA1031 // Do not catch general exception types
            finally
            {
                if (Directory.Exists(destDir))
                {
                    Directory.Delete(destDir, true);
                }
            }
        }
        /// <summary>
        /// Opens a Reader for Non-seeking usage
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static IReader Open(Stream stream, ReaderOptions options = null)
        {
            stream.CheckNotNull("stream");
            options = options ?? new ReaderOptions()
            {
                LeaveStreamOpen = false
            };
            RewindableStream rewindableStream = new RewindableStream(stream);

            rewindableStream.StartRecording();
            if (ZipArchive.IsZipFile(rewindableStream, options.Password))
            {
                rewindableStream.Rewind(true);
                return(ZipReader.Open(rewindableStream, options));
            }
            rewindableStream.Rewind(false);
            if (GZipArchive.IsGZipFile(rewindableStream))
            {
                rewindableStream.Rewind(false);
                GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.GZip));
                }
                rewindableStream.Rewind(true);
                return(GZipReader.Open(rewindableStream, options));
            }

            rewindableStream.Rewind(false);
            if (BZip2Stream.IsBZip2(rewindableStream))
            {
                rewindableStream.Rewind(false);
                BZip2Stream testStream = new BZip2Stream(rewindableStream, CompressionMode.Decompress, true);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.BZip2));
                }
            }

            rewindableStream.Rewind(false);
            if (LZipStream.IsLZipFile(rewindableStream))
            {
                rewindableStream.Rewind(false);
                LZipStream testStream = new LZipStream(rewindableStream, CompressionMode.Decompress, true);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.LZip));
                }
            }
            rewindableStream.Rewind(false);
            if (RarArchive.IsRarFile(rewindableStream, options))
            {
                rewindableStream.Rewind(true);
                return(RarReader.Open(rewindableStream, options));
            }

            rewindableStream.Rewind(false);
            if (TarArchive.IsTarFile(rewindableStream))
            {
                rewindableStream.Rewind(true);
                return(TarReader.Open(rewindableStream, options));
            }
            rewindableStream.Rewind(false);
            if (XZStream.IsXZStream(rewindableStream))
            {
                rewindableStream.Rewind(true);
                XZStream testStream = new XZStream(rewindableStream);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.Xz));
                }
            }
            throw new InvalidOperationException("Cannot determine compressed stream type.  Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ");
        }
        public static bool TryOpen(Stream stream, ReaderOptions options, ArchiveTypeMask archiveTypes, out IReader reader)
        {
            stream.CheckNotNull("stream");
            options = options ?? new ReaderOptions()
            {
                LeaveStreamOpen = false
            };
            RewindableStream rewindableStream = new RewindableStream(stream);

            rewindableStream.StartRecording();
            if (archiveTypes.HasFlag(ArchiveTypeMask.Zip) && ZipArchive.IsZipFile(rewindableStream, options.Password))
            {
                rewindableStream.Rewind(true);
                reader = ZipReader.Open(rewindableStream, options);
                return(true);
            }
            rewindableStream.Rewind(false);
            if (archiveTypes.HasFlag(ArchiveTypeMask.GZip) && GZipArchive.IsGZipFile(rewindableStream))
            {
                rewindableStream.Rewind(false);
                GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
                if (archiveTypes.HasFlag(ArchiveTypeMask.Tar) && TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    reader = new TarReader(rewindableStream, options, CompressionType.GZip);
                    return(true);
                }
                rewindableStream.Rewind(true);
                reader = GZipReader.Open(rewindableStream, options);
                return(true);
            }

            rewindableStream.Rewind(false);
            if (archiveTypes.HasFlag(ArchiveTypeMask.BZip2) && BZip2Stream.IsBZip2(rewindableStream))
            {
                rewindableStream.Rewind(false);
                BZip2Stream testStream = new BZip2Stream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress, false);
                if (archiveTypes.HasFlag(ArchiveTypeMask.Tar) && TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    reader = new TarReader(rewindableStream, options, CompressionType.BZip2);
                    return(true);
                }
            }

            rewindableStream.Rewind(false);
            if (archiveTypes.HasFlag(ArchiveTypeMask.LZip) && LZipStream.IsLZipFile(rewindableStream))
            {
                rewindableStream.Rewind(false);
                LZipStream testStream = new LZipStream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress);
                if (archiveTypes.HasFlag(ArchiveTypeMask.Tar) && TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    reader = new TarReader(rewindableStream, options, CompressionType.LZip);
                    return(true);
                }
            }
            rewindableStream.Rewind(false);
            if (archiveTypes.HasFlag(ArchiveTypeMask.Rar) && RarArchive.IsRarFile(rewindableStream, options))
            {
                rewindableStream.Rewind(true);
                reader = RarReader.Open(rewindableStream, options);
                return(true);
            }

            rewindableStream.Rewind(false);
            if (archiveTypes.HasFlag(ArchiveTypeMask.Tar) && TarArchive.IsTarFile(rewindableStream))
            {
                rewindableStream.Rewind(true);
                reader = TarReader.Open(rewindableStream, options);
                return(true);
            }
            rewindableStream.Rewind(false);
            if (XZStream.IsXZStream(rewindableStream))
            {
                rewindableStream.Rewind(true);
                XZStream testStream = new XZStream(rewindableStream);
                if (archiveTypes.HasFlag(ArchiveTypeMask.Tar) && TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    reader = new TarReader(rewindableStream, options, CompressionType.Xz);
                    return(true);
                }
            }
            reader = null;
            return(false);
        }
Beispiel #23
0
        public async Task Unpack(VirtualFile file, VirtualDirectory destination,
                                 IProgressNotifier parentProgress = null, ChangeObservable observable = null)
        {
            if (Path.GetExtension(file.Name)?.Equals(".zip", StringComparison.OrdinalIgnoreCase) == true)
            {
                await UnpackZipFile().ConfigureAwait(false);
            }
            else if (file.Name.EndsWith(".tar.xz", StringComparison.OrdinalIgnoreCase))
            {
                UnpackTarXzFile(file);
            }
            else if (Path.GetExtension(file.Name)?.Equals(".xz", StringComparison.OrdinalIgnoreCase) == true)
            {
                UnpackXzFile(file);
            }
            else if (Path.GetExtension(file.Name)?.Equals(".tar", StringComparison.OrdinalIgnoreCase) == true)
            {
                UnpackTarFile(file);
            }
            else if (Path.GetExtension(file.Name)?.Equals(".sh", StringComparison.OrdinalIgnoreCase) == true &&
                     environmentService.Platform != OSPlatform.Windows)
            {
                await UnpackSelfExtractingShellScript().ConfigureAwait(false);
            }
            else
            {
                throw new UnsupportedArchiveFormatException(file.FullName);
            }

            async Task UnpackSelfExtractingShellScript()
            {
                ValidateShellScript();
                StringBuilderUserInterface userInterface = new StringBuilderUserInterface(log, writeInformation: true, writeError: true);

                try
                {
                    using (parentProgress?.SpawnInfiniteProgress("Executing the shell script."))
                        using (IProcess process = processManager.StartProcess(file.FullName, $"-y -d \"{destination.FullName}\"", userInterface))
                        {
                            await process.WaitForExitAsync().ConfigureAwait(false);

                            if (process.ExitCode != 0)
                            {
                                throw new UnsupportedArchiveFormatException(file.FullName,
                                                                            new FormattableException(
                                                                                $"An error occured while executing the script.{Environment.NewLine}" +
                                                                                $"{userInterface.Error}"));
                            }
                        }
                }
                catch (Exception e)
                {
                    if (e is FormattableException)
                    {
                        throw;
                    }
                    throw new UnsupportedArchiveFormatException(file.FullName,
                                                                new FormattableException(
                                                                    $"An exception occured while executing the script.{Environment.NewLine}" +
                                                                    $"{e.Message}", e));
                }

                void ValidateShellScript()
                {
                    StringBuilderUserInterface validationUserInterface = new StringBuilderUserInterface(log, writeInformation: true, writeError: true);

                    try
                    {
                        using (IProcess process = processManager.StartProcess(file.FullName, "--help", validationUserInterface))
                        {
                            process.WaitForExit();
                        }
                    }
                    catch (UnauthorizedAccessException e)
                    {
                        throw new UnsupportedArchiveFormatException(file.FullName,
                                                                    new FormattableException(
                                                                        $"An exception occured while inspecting the script.{Environment.NewLine}" +
                                                                        $"This excpetion can occur when the file is not marked as executable.{Environment.NewLine}" +
                                                                        $"{e.Message}", e));
                    }
                    catch (Exception e)
                    {
                        if (e is FormattableException)
                        {
                            throw;
                        }
                        throw new UnsupportedArchiveFormatException(file.FullName,
                                                                    new FormattableException(
                                                                        $"An exception occured while inspecting the script.{Environment.NewLine}" +
                                                                        $"{e.Message}", e));
                    }

                    if (!Regex.IsMatch(validationUserInterface.Information,
                                       @"(?=.*(?:usage|Usage)).*(?=.*-y)(?=.*-d)"))
                    {
                        throw new UnsupportedArchiveFormatException(file.FullName,
                                                                    new FormattableException($"Did not find the expected usage information.{Environment.NewLine}" +
                                                                                             $"The expected information need to include the options '-y' and '-d'.{Environment.NewLine}" +
                                                                                             $"The following usage information was given:{Environment.NewLine}" +
                                                                                             $"{validationUserInterface.Information}"));
                    }
                }
            }

            async Task UnpackZipFile()
            {
                using (Stream fileStream = file.OpenRead())
                    using (ZipFile zipFile = new ZipFile(fileStream))
                        using (IProgressNotifier mainProgress = parentProgress?.Spawn(2, $"Extracting {file.FullName} to {destination.FullName}."))
                        {
                            archiveResultBuilder.Clear();
                            using (mainProgress?.SpawnInfiniteProgress("Test archive integrity."))
                            {
                                ZipFile copy = zipFile;
                                await Task.Run(() =>
                                {
                                    if (!copy.TestArchive(true, TestStrategy.FindAllErrors, ResultHandler))
                                    {
                                        throw new UnsupportedArchiveFormatException(
                                            file.FullName, new FormattableException(archiveResultBuilder.ToString()));
                                    }
                                }).ConfigureAwait(false);
                            }

                            double increment = (double)Constants.ProgressMaxResolution / zipFile.Count + 1;
                            using (IProgressNotifier extractProgress = mainProgress?.Spawn(Constants.ProgressMaxResolution, "Extract files"))
                            {
                                foreach (ZipEntry zipEntry in zipFile)
                                {
                                    extractProgress?.TickIncrement(increment);
                                    if (!zipEntry.IsFile)
                                    {
                                        continue;   // Ignore directories
                                    }

                                    byte[] buffer = new byte[Constants.StreamCopyBufferSize]; // 4K is optimum

                                    using (Stream zipStream = zipFile.GetInputStream(zipEntry))
                                    {
                                        string[]         path            = fileSystem.GetPath(zipEntry.Name);
                                        VirtualDirectory fileDestination = destination.Directory(path.Take(path.Length - 1).ToArray());
                                        VirtualFile      entryFile       = fileDestination.File(path.Last());

                                        // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
                                        // of the file, but does not waste memory.
                                        using (Stream streamWriter = entryFile.OpenWrite())
                                        {
                                            StreamUtils.Copy(zipStream, streamWriter, buffer);
                                        }
                                    }
                                }
                            }
                        }
            }

            VirtualFile UnpackXzFile(VirtualFile packedFile)
            {
                using (Stream fileStream = packedFile.OpenRead())
                    using (XZStream xzStream = new XZStream(fileStream))
                        using (parentProgress?.SpawnInfiniteProgress($"Extracting {packedFile.Name}..."))
                        {
                            string[] path             = fileSystem.GetPath(packedFile.FullName);
                            string   relativeFilePath = path.Last().Substring(0, path.Last().LastIndexOf(".xz", StringComparison.OrdinalIgnoreCase));
                            if (destination.FileExists(relativeFilePath))
                            {
                                destination.File(relativeFilePath).Delete();
                            }
                            VirtualFile destinationFile = destination.File(relativeFilePath);
                            observable?.OnNext(new Change(() => destinationFile.Restore()));

                            byte[] buffer = new byte[Constants.StreamCopyBufferSize]; // 4K is optimum

                            using (Stream streamWriter = destinationFile.OpenWrite())
                            {
                                StreamUtils.Copy(xzStream, streamWriter, buffer);
                                return(destinationFile);
                            }
                        }
            }

            void UnpackTarFile(VirtualFile packedFile)
            {
                //sharpcompress
                using (Stream fileStream = packedFile.OpenRead())
                    using (TarArchive tarArchive = TarArchive.Open(fileStream))
                    {
                        double increment = (double)Constants.ProgressMaxResolution / tarArchive.Entries.Count;
                        using (IProgressNotifier extractProgress = parentProgress?.Spawn(Constants.ProgressMaxResolution, "Extracting .tar archive"))
                        {
                            foreach (TarArchiveEntry tarEntry in tarArchive.Entries)
                            {
                                extractProgress?.TickIncrement(increment);
                                if (tarEntry.IsDirectory)
                                {
                                    continue;       // Ignore directories
                                }

                                byte[] buffer = new byte[Constants.StreamCopyBufferSize]; // 4K is optimum

                                using (Stream tarStream = tarEntry.OpenEntryStream())
                                {
                                    string[]         path            = fileSystem.GetPath(tarEntry.Key);
                                    VirtualDirectory fileDestination = destination.Directory(path.Take(path.Length - 1).ToArray());
                                    if (fileDestination.FileExists(path.Last()))
                                    {
                                        fileDestination.File(path.Last()).Delete();
                                    }
                                    VirtualFile entryFile = fileDestination.File(path.Last());
                                    observable?.OnNext(new Change(() => entryFile.Restore()
                                                                  //, $"Unpack {tarEntry.Key}."
                                                                  ));

                                    //Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
                                    // of the file, but does not waste memory.
                                    using (Stream streamWriter = entryFile.OpenWrite())
                                    {
                                        StreamUtils.Copy(tarStream, streamWriter, buffer);
                                    }
                                }
                            }
                        }
                    }
            }

            void UnpackTarXzFile(VirtualFile packedFile)
            {
                using (IProgressNotifier subProgress = parentProgress?.Spawn(2))
                {
                    parentProgress = subProgress;
                    VirtualFile tarFile = UnpackXzFile(packedFile);
                    UnpackTarFile(tarFile);
                    tarFile.Delete();
                }
            }
        }