Пример #1
0
        void Zf_SaveProgress(object sender, SaveProgressEventArgs e)
        {
            if (e.CurrentEntry != null &&
                e.CurrentEntry.FileName != _zipCurrentEntryName)
            {
                _zipCurrentEntryName = e.CurrentEntry.FileName;
                _filePosition++;

                SetProgress2?.Invoke(this, new ProgressEventArgs
                {
                    Value = _filePosition
                });

                if (!_filesByMachine.TryGetValue(e.CurrentEntry.FileName, out FileByMachine fileByMachine))
                {
                    if (!_filesByMachine.TryGetValue(e.CurrentEntry.FileName.Replace('/', '\\'), out fileByMachine))
                    {
                        throw new ArgumentException(Localization.CannotFindZipEntryInDictionary);
                    }
                }

                DbFile currentFile = fileByMachine.File;

                SetMessage3?.Invoke(this, new MessageEventArgs
                {
                    Message = string.Format(Localization.Compressing, e.CurrentEntry.FileName)
                });

                SetProgress3Bounds?.Invoke(this, new ProgressBoundsEventArgs
                {
                    Minimum = 0,
                    Maximum = currentFile.Size
                });
            }

            SetProgress3?.Invoke(this, new ProgressEventArgs
            {
                Value = e.BytesTransferred
            });

            switch (e.EventType)
            {
            case ZipProgressEventType.Error_Saving:
                #if DEBUG
                throw new Exception();
                #endif

                break;

            case ZipProgressEventType.Saving_Completed:
                _machinePosition++;
                CompressNextMachine();

                break;
            }
        }
Пример #2
0
        void CompressNextMachine()
        {
            SetProgress?.Invoke(this, new ProgressEventArgs
            {
                Value = _machinePosition
            });

            if (_machinePosition >= _machines.Length)
            {
                SetMessage?.Invoke(this, new MessageEventArgs
                {
                    Message = Localization.Finished
                });

                WorkFinished?.Invoke(this, System.EventArgs.Empty);

                return;
            }

            Machine machine = _machines[_machinePosition];

            SetMessage2?.Invoke(this, new MessageEventArgs
            {
                Message = machine.Name
            });

            using var ctx = Context.Create(Settings.Settings.Current.DatabasePath);

            string machineName = machine.Name;

            Dictionary <string, MediaByMachine> mediasByMachine = ctx.MediasByMachines.
                                                                  Where(f => f.Machine.Id == machine.Id &&
                                                                        f.Media.IsInRepo).
                                                                  ToDictionary(f => f.Name);

            if (mediasByMachine.Count > 0)
            {
                SetProgress2Bounds?.Invoke(this, new ProgressBoundsEventArgs
                {
                    Minimum = 0,
                    Maximum = mediasByMachine.Count
                });

                if (machineName.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
                {
                    machineName = machineName.Substring(0, machineName.Length - 4);
                }

                string machinePath = Path.Combine(_outPath, machineName);

                if (!Directory.Exists(machinePath))
                {
                    Directory.CreateDirectory(machinePath);
                }

                long mediaPosition = 0;

                foreach (KeyValuePair <string, MediaByMachine> mediaByMachine in mediasByMachine)
                {
                    string outputPath = Path.Combine(machinePath, mediaByMachine.Key);

                    if (!outputPath.EndsWith(".aif", StringComparison.InvariantCultureIgnoreCase))
                    {
                        outputPath += ".aif";
                    }

                    SetProgress2?.Invoke(this, new ProgressEventArgs
                    {
                        Value = mediaPosition
                    });

                    string repoPath   = null;
                    string md5Path    = null;
                    string sha1Path   = null;
                    string sha256Path = null;

                    DbMedia media = mediaByMachine.Value.Media;

                    if (media.Sha256 != null)
                    {
                        byte[] sha256Bytes = new byte[32];
                        string sha256      = media.Sha256;

                        for (int i = 0; i < 32; i++)
                        {
                            if (sha256[i * 2] >= 0x30 &&
                                sha256[i * 2] <= 0x39)
                            {
                                sha256Bytes[i] = (byte)((sha256[i * 2] - 0x30) * 0x10);
                            }
                            else if (sha256[i * 2] >= 0x41 &&
                                     sha256[i * 2] <= 0x46)
                            {
                                sha256Bytes[i] = (byte)((sha256[i * 2] - 0x37) * 0x10);
                            }
                            else if (sha256[i * 2] >= 0x61 &&
                                     sha256[i * 2] <= 0x66)
                            {
                                sha256Bytes[i] = (byte)((sha256[i * 2] - 0x57) * 0x10);
                            }

                            if (sha256[(i * 2) + 1] >= 0x30 &&
                                sha256[(i * 2) + 1] <= 0x39)
                            {
                                sha256Bytes[i] += (byte)(sha256[(i * 2) + 1] - 0x30);
                            }
                            else if (sha256[(i * 2) + 1] >= 0x41 &&
                                     sha256[(i * 2) + 1] <= 0x46)
                            {
                                sha256Bytes[i] += (byte)(sha256[(i * 2) + 1] - 0x37);
                            }
                            else if (sha256[(i * 2) + 1] >= 0x61 &&
                                     sha256[(i * 2) + 1] <= 0x66)
                            {
                                sha256Bytes[i] += (byte)(sha256[(i * 2) + 1] - 0x57);
                            }
                        }

                        string sha256B32 = Base32.ToBase32String(sha256Bytes);

                        sha256Path = Path.Combine(Settings.Settings.Current.RepositoryPath, "aaru", "sha256",
                                                  sha256B32[0].ToString(), sha256B32[1].ToString(),
                                                  sha256B32[2].ToString(), sha256B32[3].ToString(),
                                                  sha256B32[4].ToString(), sha256B32 + ".aif");
                    }

                    if (media.Sha1 != null)
                    {
                        byte[] sha1Bytes = new byte[20];
                        string sha1      = media.Sha1;

                        for (int i = 0; i < 20; i++)
                        {
                            if (sha1[i * 2] >= 0x30 &&
                                sha1[i * 2] <= 0x39)
                            {
                                sha1Bytes[i] = (byte)((sha1[i * 2] - 0x30) * 0x10);
                            }
                            else if (sha1[i * 2] >= 0x41 &&
                                     sha1[i * 2] <= 0x46)
                            {
                                sha1Bytes[i] = (byte)((sha1[i * 2] - 0x37) * 0x10);
                            }
                            else if (sha1[i * 2] >= 0x61 &&
                                     sha1[i * 2] <= 0x66)
                            {
                                sha1Bytes[i] = (byte)((sha1[i * 2] - 0x57) * 0x10);
                            }

                            if (sha1[(i * 2) + 1] >= 0x30 &&
                                sha1[(i * 2) + 1] <= 0x39)
                            {
                                sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x30);
                            }
                            else if (sha1[(i * 2) + 1] >= 0x41 &&
                                     sha1[(i * 2) + 1] <= 0x46)
                            {
                                sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x37);
                            }
                            else if (sha1[(i * 2) + 1] >= 0x61 &&
                                     sha1[(i * 2) + 1] <= 0x66)
                            {
                                sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x57);
                            }
                        }

                        string sha1B32 = Base32.ToBase32String(sha1Bytes);

                        sha1Path = Path.Combine(Settings.Settings.Current.RepositoryPath, "aaru", "sha1",
                                                sha1B32[0].ToString(), sha1B32[1].ToString(), sha1B32[2].ToString(),
                                                sha1B32[3].ToString(), sha1B32[4].ToString(), sha1B32 + ".aif");
                    }

                    if (media.Md5 != null)
                    {
                        byte[] md5Bytes = new byte[16];
                        string md5      = media.Md5;

                        for (int i = 0; i < 16; i++)
                        {
                            if (md5[i * 2] >= 0x30 &&
                                md5[i * 2] <= 0x39)
                            {
                                md5Bytes[i] = (byte)((md5[i * 2] - 0x30) * 0x10);
                            }
                            else if (md5[i * 2] >= 0x41 &&
                                     md5[i * 2] <= 0x46)
                            {
                                md5Bytes[i] = (byte)((md5[i * 2] - 0x37) * 0x10);
                            }
                            else if (md5[i * 2] >= 0x61 &&
                                     md5[i * 2] <= 0x66)
                            {
                                md5Bytes[i] = (byte)((md5[i * 2] - 0x57) * 0x10);
                            }

                            if (md5[(i * 2) + 1] >= 0x30 &&
                                md5[(i * 2) + 1] <= 0x39)
                            {
                                md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x30);
                            }
                            else if (md5[(i * 2) + 1] >= 0x41 &&
                                     md5[(i * 2) + 1] <= 0x46)
                            {
                                md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x37);
                            }
                            else if (md5[(i * 2) + 1] >= 0x61 &&
                                     md5[(i * 2) + 1] <= 0x66)
                            {
                                md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x57);
                            }
                        }

                        string md5B32 = Base32.ToBase32String(md5Bytes);

                        md5Path = Path.Combine(Settings.Settings.Current.RepositoryPath, "aaru", "md5",
                                               md5B32[0].ToString(), md5B32[1].ToString(), md5B32[2].ToString(),
                                               md5B32[3].ToString(), md5B32[4].ToString(), md5B32 + ".aif");
                    }

                    if (File.Exists(sha256Path))
                    {
                        repoPath = sha256Path;
                    }
                    else if (File.Exists(sha1Path))
                    {
                        repoPath = sha1Path;
                    }
                    else if (File.Exists(md5Path))
                    {
                        repoPath = md5Path;
                    }

                    if (repoPath == null)
                    {
                        throw new ArgumentException(string.Format(Localization.CannotFindHashInRepository,
                                                                  media.Sha256 ?? media.Sha1 ?? media.Md5));
                    }

                    var inFs  = new FileStream(repoPath, FileMode.Open, FileAccess.Read);
                    var outFs = new FileStream(outputPath, FileMode.Create, FileAccess.Write);

                    SetMessage3?.Invoke(this, new MessageEventArgs
                    {
                        Message = string.Format(Localization.Copying, Path.GetFileName(outputPath))
                    });

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

                    byte[] buffer = new byte[BUFFER_SIZE];

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

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

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

                    SetProgress3?.Invoke(this, new ProgressEventArgs
                    {
                        Value = inFs.Position
                    });

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

                    inFs.Close();
                    outFs.Close();

                    mediaPosition++;
                }
            }

            Dictionary <string, DiskByMachine> disksByMachine = ctx.DisksByMachines.
                                                                Where(f => f.Machine.Id == machine.Id &&
                                                                      f.Disk.IsInRepo).
                                                                ToDictionary(f => f.Name);

            if (disksByMachine.Count > 0)
            {
                SetProgress2Bounds?.Invoke(this, new ProgressBoundsEventArgs
                {
                    Minimum = 0,
                    Maximum = disksByMachine.Count
                });

                if (machineName.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
                {
                    machineName = machineName.Substring(0, machineName.Length - 4);
                }

                string machinePath = Path.Combine(_outPath, machineName);

                if (!Directory.Exists(machinePath))
                {
                    Directory.CreateDirectory(machinePath);
                }

                long diskPosition = 0;

                foreach (KeyValuePair <string, DiskByMachine> diskByMachine in disksByMachine)
                {
                    string outputPath = Path.Combine(machinePath, diskByMachine.Key);

                    if (!outputPath.EndsWith(".chd", StringComparison.InvariantCultureIgnoreCase))
                    {
                        outputPath += ".chd";
                    }

                    SetProgress2?.Invoke(this, new ProgressEventArgs
                    {
                        Value = diskPosition
                    });

                    string repoPath = null;
                    string md5Path  = null;
                    string sha1Path = null;

                    DbDisk disk = diskByMachine.Value.Disk;

                    if (disk.Sha1 != null)
                    {
                        byte[] sha1Bytes = new byte[20];
                        string sha1      = disk.Sha1;

                        for (int i = 0; i < 20; i++)
                        {
                            if (sha1[i * 2] >= 0x30 &&
                                sha1[i * 2] <= 0x39)
                            {
                                sha1Bytes[i] = (byte)((sha1[i * 2] - 0x30) * 0x10);
                            }
                            else if (sha1[i * 2] >= 0x41 &&
                                     sha1[i * 2] <= 0x46)
                            {
                                sha1Bytes[i] = (byte)((sha1[i * 2] - 0x37) * 0x10);
                            }
                            else if (sha1[i * 2] >= 0x61 &&
                                     sha1[i * 2] <= 0x66)
                            {
                                sha1Bytes[i] = (byte)((sha1[i * 2] - 0x57) * 0x10);
                            }

                            if (sha1[(i * 2) + 1] >= 0x30 &&
                                sha1[(i * 2) + 1] <= 0x39)
                            {
                                sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x30);
                            }
                            else if (sha1[(i * 2) + 1] >= 0x41 &&
                                     sha1[(i * 2) + 1] <= 0x46)
                            {
                                sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x37);
                            }
                            else if (sha1[(i * 2) + 1] >= 0x61 &&
                                     sha1[(i * 2) + 1] <= 0x66)
                            {
                                sha1Bytes[i] += (byte)(sha1[(i * 2) + 1] - 0x57);
                            }
                        }

                        string sha1B32 = Base32.ToBase32String(sha1Bytes);

                        sha1Path = Path.Combine(Settings.Settings.Current.RepositoryPath, "chd", "sha1",
                                                sha1B32[0].ToString(), sha1B32[1].ToString(), sha1B32[2].ToString(),
                                                sha1B32[3].ToString(), sha1B32[4].ToString(), sha1B32 + ".chd");
                    }

                    if (disk.Md5 != null)
                    {
                        byte[] md5Bytes = new byte[16];
                        string md5      = disk.Md5;

                        for (int i = 0; i < 16; i++)
                        {
                            if (md5[i * 2] >= 0x30 &&
                                md5[i * 2] <= 0x39)
                            {
                                md5Bytes[i] = (byte)((md5[i * 2] - 0x30) * 0x10);
                            }
                            else if (md5[i * 2] >= 0x41 &&
                                     md5[i * 2] <= 0x46)
                            {
                                md5Bytes[i] = (byte)((md5[i * 2] - 0x37) * 0x10);
                            }
                            else if (md5[i * 2] >= 0x61 &&
                                     md5[i * 2] <= 0x66)
                            {
                                md5Bytes[i] = (byte)((md5[i * 2] - 0x57) * 0x10);
                            }

                            if (md5[(i * 2) + 1] >= 0x30 &&
                                md5[(i * 2) + 1] <= 0x39)
                            {
                                md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x30);
                            }
                            else if (md5[(i * 2) + 1] >= 0x41 &&
                                     md5[(i * 2) + 1] <= 0x46)
                            {
                                md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x37);
                            }
                            else if (md5[(i * 2) + 1] >= 0x61 &&
                                     md5[(i * 2) + 1] <= 0x66)
                            {
                                md5Bytes[i] += (byte)(md5[(i * 2) + 1] - 0x57);
                            }
                        }

                        string md5B32 = Base32.ToBase32String(md5Bytes);

                        md5Path = Path.Combine(Settings.Settings.Current.RepositoryPath, "chd", "md5",
                                               md5B32[0].ToString(), md5B32[1].ToString(), md5B32[2].ToString(),
                                               md5B32[3].ToString(), md5B32[4].ToString(), md5B32 + ".chd");
                    }

                    if (File.Exists(sha1Path))
                    {
                        repoPath = sha1Path;
                    }
                    else if (File.Exists(md5Path))
                    {
                        repoPath = md5Path;
                    }

                    if (repoPath == null)
                    {
                        throw new ArgumentException(string.Format(Localization.CannotFindHashInRepository,
                                                                  disk.Sha1 ?? disk.Md5));
                    }

                    var inFs  = new FileStream(repoPath, FileMode.Open, FileAccess.Read);
                    var outFs = new FileStream(outputPath, FileMode.Create, FileAccess.Write);

                    SetMessage3?.Invoke(this, new MessageEventArgs
                    {
                        Message = string.Format(Localization.Copying, Path.GetFileName(outputPath))
                    });

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

                    byte[] buffer = new byte[BUFFER_SIZE];

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

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

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

                    SetProgress3?.Invoke(this, new ProgressEventArgs
                    {
                        Value = inFs.Position
                    });

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

                    inFs.Close();
                    outFs.Close();

                    diskPosition++;
                }
            }

            _filesByMachine = ctx.FilesByMachines.Where(f => f.Machine.Id == machine.Id && f.File.IsInRepo).
                              ToDictionary(f => f.Name);

            if (_filesByMachine.Count == 0)
            {
                _machinePosition++;
                Task.Run(CompressNextMachine);

                return;
            }

            SetProgress2Bounds?.Invoke(this, new ProgressBoundsEventArgs
            {
                Minimum = 0,
                Maximum = _filesByMachine.Count
            });

            if (!machineName.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
            {
                machineName += ".zip";
            }

            var zf = new ZipFile(Path.Combine(_outPath, machineName), Encoding.UTF8)
            {
                CompressionLevel  = CompressionLevel.BestCompression,
                CompressionMethod = CompressionMethod.Deflate,
                EmitTimesInUnixFormatWhenSaving    = true,
                EmitTimesInWindowsFormatWhenSaving = true,
                UseZip64WhenSaving      = Zip64Option.AsNecessary,
                SortEntriesBeforeSaving = true
            };

            zf.SaveProgress += Zf_SaveProgress;

            foreach (KeyValuePair <string, FileByMachine> fileByMachine in _filesByMachine)
            {
                // Is a directory
                if ((fileByMachine.Key.EndsWith("/", StringComparison.InvariantCultureIgnoreCase) ||
                     fileByMachine.Key.EndsWith("\\", StringComparison.InvariantCultureIgnoreCase)) &&
                    fileByMachine.Value.File.Size == 0)
                {
                    ZipEntry zd = zf.AddDirectoryByName(fileByMachine.Key.Replace('/', '\\'));
                    zd.Attributes   = FileAttributes.Normal;
                    zd.CreationTime = DateTime.UtcNow;
                    zd.AccessedTime = DateTime.UtcNow;
                    zd.LastModified = DateTime.UtcNow;
                    zd.ModifiedTime = DateTime.UtcNow;

                    continue;
                }

                ZipEntry zi = zf.AddEntry(fileByMachine.Key, Zf_HandleOpen, Zf_HandleClose);
                zi.Attributes   = FileAttributes.Normal;
                zi.CreationTime = DateTime.UtcNow;
                zi.AccessedTime = DateTime.UtcNow;
                zi.LastModified = DateTime.UtcNow;
                zi.ModifiedTime = DateTime.UtcNow;
            }

            zf.Save();
        }