예제 #1
0
 /// <summary>
 /// 压缩
 /// </summary>
 /// <param name="bytes">需要压缩的字节流</param>
 /// <returns>压缩后的结果</returns>
 public byte[] Compress(byte[] bytes)
 {
     using (var ms = new MemoryStream())
     {
         var lzma = new LZipStream(ms, CompressionMode.Compress, true);
         lzma.Write(bytes, 0, bytes.Length);
         lzma.Close();
         return(ms.ToArray());
     }
 }
예제 #2
0
        public void DecompressFile(string source, string destination)
        {
            var    inFs    = new FileStream(source, FileMode.Open, FileAccess.Read);
            var    outFs   = new FileStream(destination, FileMode.Create, FileAccess.Write);
            Stream zStream = new LZipStream(inFs, CompressionMode.Decompress);

            zStream.CopyTo(outFs);

            outFs.Close();
            zStream.Close();
            inFs.Close();
        }
예제 #3
0
 /// <summary>
 /// 解压缩
 /// </summary>
 /// <param name="bytes">需要解压缩的字节流</param>
 /// <returns>解压缩的结果</returns>
 public byte[] Decompress(byte[] bytes)
 {
     using (var ms = new MemoryStream())
     {
         var lzma  = new LZipStream(new MemoryStream(bytes), CompressionMode.Decompress, true);
         var count = 0;
         var data  = new byte[4096];
         while ((count = lzma.Read(data, 0, data.Length)) != 0)
         {
             ms.Write(data, 0, count);
         }
         lzma.Close();
         return(ms.ToArray());
     }
 }
예제 #4
0
        public void CompressFile(string source, string destination)
        {
            var    inFs    = new FileStream(source, FileMode.Open, FileAccess.Read);
            var    outFs   = new FileStream(destination, FileMode.CreateNew, FileAccess.Write);
            Stream zStream = new LZipStream(outFs, CompressionMode.Compress);

            byte[] buffer = new byte[BUFFER_SIZE];

            SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs
            {
                Minimum = 0,
                Maximum = inFs.Length
            });

            while (inFs.Position + BUFFER_SIZE <= inFs.Length)
            {
                SetProgress?.Invoke(this, new ProgressEventArgs
                {
                    Value = inFs.Position
                });

                inFs.Read(buffer, 0, buffer.Length);
                zStream.Write(buffer, 0, buffer.Length);
            }

            buffer = new byte[inFs.Length - inFs.Position];

            SetProgressBounds?.Invoke(this, new ProgressBoundsEventArgs
            {
                Minimum = 0,
                Maximum = inFs.Length
            });

            inFs.Read(buffer, 0, buffer.Length);
            zStream.Write(buffer, 0, buffer.Length);

            inFs.Close();
            zStream.Close();
            outFs.Dispose();
        }
예제 #5
0
        public static void ClamScanFileFromRepo(DbFile file)
        {
            try
            {
                if (Context.ClamdVersion == null)
                {
                    Failed?.Invoke("clamd is not usable");
                    return;
                }

                if (clam == null)
                {
                    Failed?.Invoke("clamd is not initalized");
                }

                string   repoPath;
                AlgoEnum algorithm;

                if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                             file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                             file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".gz")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".gz");
                    algorithm = AlgoEnum.GZip;
                }
                else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                  file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                  file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                  file.Sha256 + ".bz2")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".bz2");
                    algorithm = AlgoEnum.BZip2;
                }
                else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                  file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                  file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                  file.Sha256 + ".lzma")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                            file.Sha256 + ".lzma");
                    algorithm = AlgoEnum.LZMA;
                }
                else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                  file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                  file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                  file.Sha256 + ".lz")))
                {
                    repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                            file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                            file.Sha256[3].ToString(), file.Sha256[4].ToString(), file.Sha256 + ".lz");
                    algorithm = AlgoEnum.LZip;
                }
                else
                {
                    Failed?.Invoke($"Cannot find file with hash {file.Sha256} in the repository");
                    return;
                }

                ClamScanResult result  = null;
                Stream         zStream = null;

                if (Settings.Current.ClamdIsLocal)
                {
                    if (algorithm == AlgoEnum.LZMA || algorithm == AlgoEnum.LZip)
                    {
                        string     tmpFile = Path.Combine(Settings.Current.TemporaryFolder, Path.GetTempFileName());
                        FileStream outFs   = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
                        FileStream inFs    = new FileStream(repoPath, FileMode.Open, FileAccess.Read);

                        if (algorithm == AlgoEnum.LZMA)
                        {
                            byte[] properties = new byte[5];
                            inFs.Read(properties, 0, 5);
                            inFs.Seek(8, SeekOrigin.Current);
                            zStream = new LzmaStream(properties, inFs, inFs.Length - 13, file.Length);
                        }
                        else
                        {
                            zStream = new LZipStream(inFs, CompressionMode.Decompress);
                        }

                        UpdateProgress?.Invoke("Uncompressing file...", null, 0, 0);

                        #if DEBUG
                        stopwatch.Restart();
                        #endif
                        zStream.CopyTo(outFs);
                        zStream.Close();
                        outFs.Close();
                        #if DEBUG
                        stopwatch.Stop();
                        Console.WriteLine("Core.ClamScanFileFromRepo({0}): Uncompressing took {1} seconds", file,
                                          stopwatch.Elapsed.TotalSeconds);
                        #endif

                        UpdateProgress?.Invoke("Requesting local scan to clamd server...", null, 0, 0);

                        #if DEBUG
                        stopwatch.Restart();
                        #endif
                        Task.Run(async() => { result = await clam.ScanFileOnServerMultithreadedAsync(tmpFile); })
                        .Wait();
                        #if DEBUG
                        stopwatch.Stop();
                        Console.WriteLine("Core.ClamScanFileFromRepo({0}): Clamd took {1} seconds to scan", file,
                                          stopwatch.Elapsed.TotalSeconds);
                        #endif

                        File.Delete(tmpFile);
                    }
                    else
                    {
                        UpdateProgress?.Invoke("Requesting local scan to clamd server...", null, 0, 0);

                        #if DEBUG
                        stopwatch.Restart();
                        #endif
                        Task.Run(async() => { result = await clam.ScanFileOnServerMultithreadedAsync(repoPath); })
                        .Wait();
                        #if DEBUG
                        stopwatch.Stop();
                        Console.WriteLine("Core.ClamScanFileFromRepo({0}): Clamd took {1} seconds to scan", file,
                                          stopwatch.Elapsed.TotalSeconds);
                        #endif
                    }
                }
                else
                {
                    FileStream inFs = new FileStream(repoPath, FileMode.Open, FileAccess.Read);

                    switch (algorithm)
                    {
                    case AlgoEnum.GZip:
                        zStream = new GZipStream(inFs, CompressionMode.Decompress);
                        break;

                    case AlgoEnum.BZip2:
                        zStream = new BZip2Stream(inFs, CompressionMode.Decompress);
                        break;

                    case AlgoEnum.LZMA:
                        byte[] properties = new byte[5];
                        inFs.Read(properties, 0, 5);
                        inFs.Seek(8, SeekOrigin.Current);
                        zStream = new LzmaStream(properties, inFs, inFs.Length - 13, file.Length);
                        break;

                    case AlgoEnum.LZip:
                        zStream = new LZipStream(inFs, CompressionMode.Decompress);
                        break;
                    }

                    UpdateProgress?.Invoke("Uploading file to clamd server...", null, 0, 0);

                    #if DEBUG
                    stopwatch.Restart();
                    #endif
                    Task.Run(async() => { result = await clam.SendAndScanFileAsync(zStream); }).Wait();
                    #if DEBUG
                    stopwatch.Stop();
                    Console.WriteLine("Core.ClamScanFileFromRepo({0}): Clamd took {1} seconds to scan", file,
                                      stopwatch.Elapsed.TotalSeconds);
                    #endif
                    zStream.Close();
                }

                if (result.InfectedFiles != null && result.InfectedFiles.Count > 0)
                {
                    file.HasVirus = true;
                    file.Virus    = result.InfectedFiles[0].VirusName;
                }
                else if (file.HasVirus == null)
                {
                    // If no scan has been done, mark as false.
                    // If a positive has already existed don't overwrite it.
                    file.HasVirus = false;
                    file.Virus    = null;
                }

                file.ClamTime = DateTime.UtcNow;

                dbCore.DbOps.UpdateFile(file);

                ScanFinished?.Invoke(file);
            }
            catch (ThreadAbortException) { }
            catch (Exception ex)
            {
                Failed?.Invoke($"Exception {ex.Message} when calling clamd");
                #if DEBUG
                Console.WriteLine("Exception {0}\n{1}", ex.Message, ex.InnerException);
                #endif
            }
        }
예제 #6
0
        public static void VirusTotalFileFromRepo(DbFile file)
        {
            try
            {
                if (!Context.VirusTotalEnabled)
                {
                    Failed?.Invoke("VirusTotal is not usable");

                    return;
                }

                if (vTotal == null)
                {
                    Failed?.Invoke("VirusTotal is not initalized");
                }

                FileReport fResult = null;

                UpdateProgress?.Invoke("Requesting existing report to VirusTotal", null, 0, 0);

            #if DEBUG
                stopwatch.Restart();
            #endif
                Task.Run(async() =>
                {
                    fResult = await vTotal.GetFileReportAsync(file.Sha256);
                }).Wait();
            #if DEBUG
                stopwatch.Stop();

                Console.WriteLine("Core.VirusTotalFileFromRepo({0}): VirusTotal took {1} seconds to answer for SHA256 request",
                                  file, stopwatch.Elapsed.TotalSeconds);
            #endif

                if (fResult.ResponseCode == FileReportResponseCode.NotPresent)
                {
                    Failed?.Invoke(fResult.VerboseMsg);

                    return;
                }

                if (fResult.ResponseCode != FileReportResponseCode.Queued)
                {
                    if (fResult.ResponseCode == FileReportResponseCode.Present)
                    {
                        if (fResult.Positives > 0)
                        {
                            file.HasVirus = true;

                            if (fResult.Scans != null)
                            {
                                foreach (KeyValuePair <string, ScanEngine> engine in fResult.Scans)
                                {
                                    if (!engine.Value.Detected)
                                    {
                                        continue;
                                    }

                                    file.Virus          = engine.Value.Result;
                                    file.VirusTotalTime = engine.Value.Update;
                                    dbCore.DbOps.UpdateFile(file);

                                    ScanFinished?.Invoke(file);

                                    return;
                                }
                            }
                        }
                        else
                        {
                            // If no scan has been done, mark as false.
                            // If a positive has already existed don't overwrite it.
                            file.HasVirus       = false;
                            file.Virus          = null;
                            file.VirusTotalTime = DateTime.UtcNow;

                            dbCore.DbOps.UpdateFile(file);

                            ScanFinished?.Invoke(file);

                            return;
                        }
                    }

                    string   repoPath;
                    AlgoEnum algorithm;

                    if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                 file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                 file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                 file.Sha256 + ".gz")))
                    {
                        repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                file.Sha256 + ".gz");

                        algorithm = AlgoEnum.GZip;
                    }
                    else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                      file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                      file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                      file.Sha256 + ".bz2")))
                    {
                        repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                file.Sha256 + ".bz2");

                        algorithm = AlgoEnum.BZip2;
                    }
                    else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                      file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                      file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                      file.Sha256 + ".lzma")))
                    {
                        repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                file.Sha256 + ".lzma");

                        algorithm = AlgoEnum.LZMA;
                    }
                    else if (File.Exists(Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                      file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                      file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                      file.Sha256 + ".lz")))
                    {
                        repoPath = Path.Combine(Settings.Current.RepositoryPath, file.Sha256[0].ToString(),
                                                file.Sha256[1].ToString(), file.Sha256[2].ToString(),
                                                file.Sha256[3].ToString(), file.Sha256[4].ToString(),
                                                file.Sha256 + ".lz");

                        algorithm = AlgoEnum.LZip;
                    }
                    else
                    {
                        Failed?.Invoke($"Cannot find file with hash {file.Sha256} in the repository");

                        return;
                    }

                    UpdateProgress?.Invoke("Uncompressing file...", null, 0, 0);

                    var    inFs    = new FileStream(repoPath, FileMode.Open, FileAccess.Read);
                    Stream zStream = null;

                    switch (algorithm)
                    {
                    case AlgoEnum.GZip:
                        zStream = new GZipStream(inFs, CompressionMode.Decompress);

                        break;

                    case AlgoEnum.BZip2:
                        zStream = new BZip2Stream(inFs, CompressionMode.Decompress);

                        break;

                    case AlgoEnum.LZMA:
                        byte[] properties = new byte[5];
                        inFs.Read(properties, 0, 5);
                        inFs.Seek(8, SeekOrigin.Current);
                        zStream = new LzmaStream(properties, inFs, inFs.Length - 13, file.Length);

                        break;

                    case AlgoEnum.LZip:
                        zStream = new LZipStream(inFs, CompressionMode.Decompress);

                        break;
                    }

                    ScanResult sResult = null;

                #if DEBUG
                    stopwatch.Restart();
                #endif

                    // Cannot use zStream directly, VirusTotal.NET requests the size *sigh*
                    string tmpFile = Path.Combine(Settings.Current.TemporaryFolder, Path.GetTempFileName());
                    var    outFs   = new FileStream(tmpFile, FileMode.Create, FileAccess.ReadWrite);
                    zStream?.CopyTo(outFs);
                    zStream?.Close();
                    outFs.Seek(0, SeekOrigin.Begin);
                #if DEBUG
                    stopwatch.Stop();

                    Console.WriteLine("Core.VirusTotalFileFromRepo({0}): Uncompressing took {1} seconds", file,
                                      stopwatch.Elapsed.TotalSeconds);
                #endif

                    UpdateProgress?.Invoke("Uploading file to VirusTotal...", null, 0, 0);

                #if DEBUG
                    stopwatch.Restart();
                #endif
                    Task.Run(async() =>
                    {
                        sResult = await vTotal.ScanFileAsync(outFs, file.Sha256); // Keep filename private, sorry!
                    }).Wait();
                #if DEBUG
                    stopwatch.Stop();

                    Console.WriteLine("Core.VirusTotalFileFromRepo({0}): Upload to VirusTotal took {1} seconds", file,
                                      stopwatch.Elapsed.TotalSeconds);
                #endif
                    outFs.Close();

                    File.Delete(tmpFile);

                    if (sResult == null ||
                        sResult.ResponseCode == ScanFileResponseCode.Error)
                    {
                        if (sResult == null)
                        {
                            Failed?.Invoke("Cannot send file to VirusTotal");
                        }
                        else
                        {
                            Failed(sResult.VerboseMsg);
                        }

                        return;
                    }

                    // Seems that we are faster than them, getting a lot of "not queued" responses...
                    Thread.Sleep(2500);

                    Task.Run(async() =>
                    {
                        fResult = await vTotal.GetFileReportAsync(file.Sha256);
                    }).Wait();
                }

                UpdateProgress?.Invoke("Waiting for VirusTotal analysis...", null, 0, 0);

            #if DEBUG
                stopwatch.Restart();
            #endif
                int counter = 0;

                while (fResult.ResponseCode == FileReportResponseCode.Queued)
                {
                    // Timeout...
                    if (counter == 10)
                    {
                        break;
                    }

                    // Wait 15 seconds so we fall in the 4 requests/minute
                    Thread.Sleep(15000);

                    Task.Run(async() =>
                    {
                        fResult = await vTotal.GetFileReportAsync(file.Sha256);
                    }).Wait();

                    counter++;
                }
            #if DEBUG
                stopwatch.Stop();

                Console.WriteLine("Core.VirusTotalFileFromRepo({0}): VirusTotal took {1} seconds to do the analysis",
                                  file, stopwatch.Elapsed.TotalSeconds);
            #endif

                if (fResult.ResponseCode != FileReportResponseCode.Present)
                {
                    Failed?.Invoke(fResult.VerboseMsg);

                    return;
                }

                if (fResult.Positives > 0)
                {
                    file.HasVirus = true;

                    if (fResult.Scans == null)
                    {
                        return;
                    }

                    foreach (KeyValuePair <string, ScanEngine> engine in fResult.Scans)
                    {
                        if (!engine.Value.Detected)
                        {
                            continue;
                        }

                        file.Virus          = engine.Value.Result;
                        file.VirusTotalTime = engine.Value.Update;
                        dbCore.DbOps.UpdateFile(file);

                        ScanFinished?.Invoke(file);

                        return;
                    }
                }
                else
                {
                    // If no scan has been done, mark as false.
                    // If a positive has already existed don't overwrite it.
                    file.HasVirus       = false;
                    file.Virus          = null;
                    file.VirusTotalTime = DateTime.UtcNow;

                    dbCore.DbOps.UpdateFile(file);

                    ScanFinished?.Invoke(file);
                }
            }
            catch (Exception ex)
            {
                Failed?.Invoke($"Exception {ex.InnerException.Message} when calling VirusTotal");
            #if DEBUG
                Console.WriteLine("Exception {0}\n{1}", ex.Message, ex.InnerException);
            #endif
            }
        }
예제 #7
0
        public static void CompressFiles()
        {
            try
            {
                if (string.IsNullOrWhiteSpace(Context.DbInfo.Developer))
                {
                    Failed?.Invoke("Developer cannot be empty");
                    return;
                }

                if (string.IsNullOrWhiteSpace(Context.DbInfo.Product))
                {
                    Failed?.Invoke("Product cannot be empty");
                    return;
                }

                if (string.IsNullOrWhiteSpace(Context.DbInfo.Version))
                {
                    Failed?.Invoke("Version cannot be empty");
                    return;
                }

                string destinationFolder = "";
                destinationFolder = Path.Combine(destinationFolder, Context.DbInfo.Developer);
                destinationFolder = Path.Combine(destinationFolder, Context.DbInfo.Product);
                destinationFolder = Path.Combine(destinationFolder, Context.DbInfo.Version);
                if (!string.IsNullOrWhiteSpace(Context.DbInfo.Languages))
                {
                    destinationFolder = Path.Combine(destinationFolder, Context.DbInfo.Languages);
                }
                if (!string.IsNullOrWhiteSpace(Context.DbInfo.Architecture))
                {
                    destinationFolder = Path.Combine(destinationFolder, Context.DbInfo.Architecture);
                }
                if (Context.DbInfo.Oem)
                {
                    destinationFolder = Path.Combine(destinationFolder, "oem");
                }
                if (!string.IsNullOrWhiteSpace(Context.DbInfo.Machine))
                {
                    destinationFolder = Path.Combine(destinationFolder, "for " + Context.DbInfo.Machine);
                }

                string destinationFile = "";
                if (!string.IsNullOrWhiteSpace(Context.DbInfo.Format))
                {
                    destinationFile += "[" + Context.DbInfo.Format + "]";
                }
                if (Context.DbInfo.Files)
                {
                    if (destinationFile != "")
                    {
                        destinationFile += "_";
                    }
                    destinationFile += "files";
                }

                if (Context.DbInfo.Netinstall)
                {
                    if (destinationFile != "")
                    {
                        destinationFile += "_";
                    }
                    destinationFile += "netinstall";
                }

                if (Context.DbInfo.Source)
                {
                    if (destinationFile != "")
                    {
                        destinationFile += "_";
                    }
                    destinationFile += "source";
                }

                if (Context.DbInfo.Update)
                {
                    if (destinationFile != "")
                    {
                        destinationFile += "_";
                    }
                    destinationFile += "update";
                }

                if (Context.DbInfo.Upgrade)
                {
                    if (destinationFile != "")
                    {
                        destinationFile += "_";
                    }
                    destinationFile += "upgrade";
                }

                if (!string.IsNullOrWhiteSpace(Context.DbInfo.Description))
                {
                    if (destinationFile != "")
                    {
                        destinationFile += "_";
                    }
                    destinationFile += Context.DbInfo.Description;
                }
                else if (destinationFile == "")
                {
                    destinationFile = "archive";
                }

                string destination = Path.Combine(destinationFolder, destinationFile) + ".zip";

                Md5Context md5 = new Md5Context();
                md5.Init();
                byte[] tmp;
                string mdid = md5.Data(Encoding.UTF8.GetBytes(destination), out tmp);
                Console.WriteLine("MDID: {0}", mdid);

                if (dbCore.DbOps.ExistsOs(mdid))
                {
                    if (File.Exists(destination))
                    {
                        Failed?.Invoke("OS already exists.");
                        return;
                    }

                    Failed?.Invoke("OS already exists in the database but not in the repository, check for inconsistencies.");
                    return;
                }

                if (File.Exists(destination))
                {
                    Failed?.Invoke("OS already exists in the repository but not in the database, check for inconsistencies.");
                    return;
                }

                Context.DbInfo.Mdid = mdid;

                string filesPath;

                if (!string.IsNullOrEmpty(Context.TmpFolder) && Directory.Exists(Context.TmpFolder))
                {
                    filesPath = Context.TmpFolder;
                }
                else
                {
                    filesPath = Context.Path;
                }

                string extension = null;

                switch (Settings.Current.CompressionAlgorithm)
                {
                case AlgoEnum.GZip:
                    extension = ".gz";
                    break;

                case AlgoEnum.BZip2:
                    extension = ".bz2";
                    break;

                case AlgoEnum.LZMA:
                    extension = ".lzma";
                    break;

                case AlgoEnum.LZip:
                    extension = ".lz";
                    break;
                }

                long totalSize = 0, currentSize = 0;
                foreach (KeyValuePair <string, DbOsFile> file in Context.Hashes)
                {
                    totalSize += file.Value.Length;
                }

                #if DEBUG
                stopwatch.Restart();
                #endif
                foreach (KeyValuePair <string, DbOsFile> file in Context.Hashes)
                {
                    UpdateProgress?.Invoke("Compressing...", file.Value.Path, currentSize, totalSize);

                    destinationFolder = Path.Combine(Settings.Current.RepositoryPath, file.Value.Sha256[0].ToString(),
                                                     file.Value.Sha256[1].ToString(), file.Value.Sha256[2].ToString(),
                                                     file.Value.Sha256[3].ToString(), file.Value.Sha256[4].ToString());
                    Directory.CreateDirectory(destinationFolder);

                    destinationFile = Path.Combine(destinationFolder, file.Value.Sha256 + extension);

                    if (!File.Exists(destinationFile))
                    {
                        FileStream inFs = new FileStream(Path.Combine(filesPath, file.Value.Path), FileMode.Open,
                                                         FileAccess.Read);
                        FileStream outFs   = new FileStream(destinationFile, FileMode.CreateNew, FileAccess.Write);
                        Stream     zStream = null;

                        switch (Settings.Current.CompressionAlgorithm)
                        {
                        case AlgoEnum.GZip:
                            zStream = new GZipStream(outFs, CompressionMode.Compress,
                                                     CompressionLevel.BestCompression);
                            break;

                        case AlgoEnum.BZip2:
                            zStream = new BZip2Stream(outFs, CompressionMode.Compress);
                            break;

                        case AlgoEnum.LZMA:
                            zStream = new LzmaStream(new LzmaEncoderProperties(), false, outFs);
                            outFs.Write(((LzmaStream)zStream).Properties, 0,
                                        ((LzmaStream)zStream).Properties.Length);
                            outFs.Write(BitConverter.GetBytes(inFs.Length), 0, 8);
                            break;

                        case AlgoEnum.LZip:
                            zStream = new LZipStream(outFs, CompressionMode.Compress);
                            break;
                        }

                        byte[] buffer = new byte[BUFFER_SIZE];

                        while (inFs.Position + BUFFER_SIZE <= inFs.Length)
                        {
                            UpdateProgress2?.Invoke($"{inFs.Position / (double)inFs.Length:P}",
                                                    $"{inFs.Position} / {inFs.Length} bytes", inFs.Position,
                                                    inFs.Length);
                            UpdateProgress?.Invoke("Compressing...", file.Value.Path, currentSize, totalSize);

                            inFs.Read(buffer, 0, buffer.Length);
                            zStream.Write(buffer, 0, buffer.Length);
                            currentSize += buffer.Length;
                        }

                        buffer = new byte[inFs.Length - inFs.Position];
                        UpdateProgress2?.Invoke($"{inFs.Position / (double)inFs.Length:P}",
                                                $"{inFs.Position} / {inFs.Length} bytes", inFs.Position, inFs.Length);
                        UpdateProgress?.Invoke("Compressing...", file.Value.Path, currentSize, totalSize);

                        inFs.Read(buffer, 0, buffer.Length);
                        zStream.Write(buffer, 0, buffer.Length);
                        currentSize += buffer.Length;

                        UpdateProgress2?.Invoke($"{inFs.Length / (double)inFs.Length:P}", "Finishing...", inFs.Length,
                                                inFs.Length);

                        inFs.Close();
                        zStream.Close();
                        outFs.Dispose();
                    }
                    else
                    {
                        currentSize += file.Value.Length;
                    }
                }
                #if DEBUG
                stopwatch.Stop();
                Console.WriteLine("Core.CompressFiles(): Took {0} seconds to compress files",
                                  stopwatch.Elapsed.TotalSeconds);
                #endif

                if (Context.Metadata != null)
                {
                    MemoryStream  xms = new MemoryStream();
                    XmlSerializer xs  = new XmlSerializer(typeof(CICMMetadataType));
                    xs.Serialize(xms, Context.Metadata);
                    xms.Position = 0;

                    JsonSerializer js = new JsonSerializer
                    {
                        Formatting        = Formatting.Indented,
                        NullValueHandling = NullValueHandling.Ignore
                    };
                    MemoryStream jms = new MemoryStream();
                    StreamWriter sw  = new StreamWriter(jms, Encoding.UTF8, 1048576, true);
                    js.Serialize(sw, Context.Metadata, typeof(CICMMetadataType));
                    sw.Close();
                    jms.Position = 0;

                    destinationFolder = Path.Combine(Settings.Current.RepositoryPath, "metadata", mdid[0].ToString(),
                                                     mdid[1].ToString(), mdid[2].ToString(), mdid[3].ToString(),
                                                     mdid[4].ToString());
                    Directory.CreateDirectory(destinationFolder);

                    FileStream xfs = new FileStream(Path.Combine(destinationFolder, mdid + ".xml"), FileMode.CreateNew,
                                                    FileAccess.Write);
                    xms.CopyTo(xfs);
                    xfs.Close();
                    FileStream jfs = new FileStream(Path.Combine(destinationFolder, mdid + ".json"), FileMode.CreateNew,
                                                    FileAccess.Write);
                    jms.CopyTo(jfs);
                    jfs.Close();

                    xms.Position = 0;
                    jms.Position = 0;
                }

                FinishedWithText?.Invoke($"Correctly added operating system with MDID {mdid}");
            }
            catch (ThreadAbortException) { }
            catch (Exception ex)
            {
                if (Debugger.IsAttached)
                {
                    throw;
                }

                Failed?.Invoke($"Exception {ex.Message}\n{ex.InnerException}");
                #if DEBUG
                Console.WriteLine("Exception {0}\n{1}", ex.Message, ex.InnerException);
                #endif
            }
        }