Exemple #1
0
        private static async Task <GameFileInfo> GenerateGameFileInfo(string file, string fileName,
                                                                      string outputFolder,
#pragma warning disable IDE0034 // Simplifier l'expression 'default'
                                                                      string baseHttpLink, CancellationToken ct = default(CancellationToken))
#pragma warning restore IDE0034 // Simplifier l'expression 'default'
        {
            if (!baseHttpLink.EndsWith("/"))
            {
                baseHttpLink += "/";
            }

            var binFileName = $"{fileName.ToLower().GetHashCode():X4}.bin";
            var outFileName = Path.Combine(outputFolder, binFileName);

            await L33TZipUtils.DoCreateL33TZipFile(file, outFileName, ct);

            var fileInfo = new GameFileInfo(fileName, await Crc32Utils.DoGetCrc32FromFile(file, ct),
                                            new FileInfo(file).Length, Path.Combine(baseHttpLink, binFileName).Replace("\\", "/"),
                                            await Crc32Utils.DoGetCrc32FromFile(outFileName, ct), new FileInfo(outFileName).Length);

            return(fileInfo);
        }
        public static async Task <bool> ScanAndRepairFile(GameFileInfo fileInfo, string gameFilePath,
                                                          PathTransformer pathTransformer, IProgress <ScanSubProgress> progress = null,
                                                          int concurrentDownload = 0, CancellationToken ct = default)
        {
            var filePath = Path.Combine(gameFilePath, pathTransformer.TransformPath(fileInfo.FileName));

            //#1 Check File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Check, 0));

            Progress <double> subProgressCheck = null;

            if (progress != null)
            {
                subProgressCheck = new Progress <double>();
                subProgressCheck.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.Check, d));
                };
            }

            if (await RunFileCheck(filePath, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheck))
            {
                progress?.Report(new ScanSubProgress(ScanSubProgressStep.End, 100));
                return(true);
            }

            //#2 Download File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Download, 0));

            var tempFileName = Path.Combine(GameScannerTempPath, $"{fileInfo.FileName.GetHashCode():X4}.tmp");

            if (File.Exists(tempFileName))
            {
                File.Delete(tempFileName);
            }

            var fileDownloader = concurrentDownload == 1
                ? (IFileDownloader) new SimpleFileDownloader(fileInfo.HttpLink, tempFileName)
                : new ChunkFileDownloader(fileInfo.HttpLink, tempFileName, GameScannerTempPath,
                                          concurrentDownload);

            if (progress != null)
            {
                fileDownloader.ProgressChanged += (sender, eventArg) =>
                {
                    switch (fileDownloader.State)
                    {
                    case FileDownloaderState.Invalid:
                    case FileDownloaderState.Download:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, fileDownloader.DownloadProgress * 0.99,
                                            new ScanDownloadProgress(fileDownloader.DownloadSize, fileDownloader.BytesDownloaded,
                                                                     fileDownloader.DownloadSpeed)));
                        break;

                    case FileDownloaderState.Finalize:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 99,
                                            new ScanDownloadProgress(fileDownloader.DownloadSize, fileDownloader.BytesDownloaded,
                                                                     0)));
                        break;

                    case FileDownloaderState.Complete:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 100,
                                            new ScanDownloadProgress(fileDownloader.DownloadSize, fileDownloader.BytesDownloaded,
                                                                     0)));
                        break;

                    case FileDownloaderState.Error:
                    case FileDownloaderState.Abort:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(fileDownloader.State),
                                                              fileDownloader.State, null);
                    }
                }
            }
            ;

            await fileDownloader.DownloadAsync(ct);


            //#3 Check Downloaded File
            ct.ThrowIfCancellationRequested();

            Progress <double> subProgressCheckDown = null;

            if (progress != null)
            {
                progress.Report(new ScanSubProgress(ScanSubProgressStep.CheckDownload, 0));

                subProgressCheckDown = new Progress <double>();
                subProgressCheckDown.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckDownload, d));
                };
            }

            try
            {
                await EnsureValidGameFile(tempFileName, fileInfo.BinSize, fileInfo.BinCrc32, ct, subProgressCheckDown);
            }
            catch
            {
                if (File.Exists(tempFileName))
                {
                    File.Delete(tempFileName);
                }

                throw;
            }

            //#4 Extract downloaded file
            ct.ThrowIfCancellationRequested();
            if (L33TZipUtils.IsL33TZipFile(tempFileName))
            {
                var tempFileName2 = $"{tempFileName.Replace(".tmp", string.Empty)}.ext.tmp";
                //
                Progress <double> extractProgress = null;
                if (progress != null)
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.ExtractDownload, 0));

                    extractProgress = new Progress <double>();
                    extractProgress.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.ExtractDownload, d));
                    };
                }

                await L33TZipUtils.ExtractL33TZipFileAsync(tempFileName, tempFileName2, ct, extractProgress);

                //#4.1 Check Extracted File
                ct.ThrowIfCancellationRequested();
                Progress <double> subProgressCheckExt = null;
                if (progress != null)
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckExtractDownload, 0));

                    subProgressCheckExt = new Progress <double>();
                    subProgressCheckExt.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.CheckExtractDownload, d));
                    };
                }

                await EnsureValidGameFile(tempFileName2, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheckExt);

                File.Delete(tempFileName);

                tempFileName = tempFileName2;
            }

            //#5 Move new file to game folder
            ct.ThrowIfCancellationRequested();

            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.Finalize, 0));

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            else
            {
                var pathName = Path.GetDirectoryName(filePath);
                if (!string.IsNullOrEmpty(pathName) && !Directory.Exists(pathName))
                {
                    Directory.CreateDirectory(pathName);
                }
            }

            File.Move(tempFileName, filePath);

            //#6 End
            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.End, 100));

            return(true);
        }
Exemple #3
0
        private static async Task <bool> ScanAndRepairFile(GameFileInfo fileInfo, string gameFilePath,
                                                           IProgress <ScanAndRepairFileProgress> progress,
                                                           CancellationToken ct)
        {
            try
            {
                var filePath = Path.Combine(gameFilePath, fileInfo.FileName);

                ct.ThrowIfCancellationRequested();
                //#1 File Check
                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 1,
                                                               new ExLog(LogLevel.Info, "-------------------------\r\n" +
                                                                         $"[{fileInfo.FileName}]\r\n" +
                                                                         "-------------------------\r\n" +
                                                                         "      - Checking file...")));

                if (RunFileCheck(filePath, fileInfo.Size, fileInfo.Crc32))
                {
                    goto end;
                }

                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 5,
                                                               new ExLog(LogLevel.Warn, "          Warning: File is missing or invalid.")));

                ct.ThrowIfCancellationRequested();
                //#6 Download File
                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 6,
                                                               new ExLog(LogLevel.Info, "      - File downloading...")));

                var dowloadProgress = new Progress <DownloadFileProgress>();
                if (progress != null)
                {
                    dowloadProgress.ProgressChanged += (o, ea) =>
                    {
                        progress.Report(new ScanAndRepairFileProgress(fileInfo.FileName,
                                                                      6 + Convert.ToInt32(Math.Floor((double)ea.ProgressPercentage / 100 * (65 - 6))), ea));
                    }
                }
                ;
                var tempFileName = Path.Combine(GetTempPath(), Path.GetRandomFileName());
                var x            = new DownloadFileUtils(new Uri(fileInfo.HttpLink), tempFileName, dowloadProgress);
                await x.DoDownload(ct);

                ct.ThrowIfCancellationRequested();
                //#65 Check Downloaded File
                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 65,
                                                               new ExLog(LogLevel.Info, "      - Checking downloaded file...")));

                if (!RunFileCheck(tempFileName, fileInfo.BinSize, fileInfo.BinCrc32))
                {
                    if (File.Exists(tempFileName))
                    {
                        File.Delete(tempFileName);
                    }

                    throw new Exception("Downloaded file is invalid!");
                }

                ct.ThrowIfCancellationRequested();
                //#70 Extract downloaded file
                var tmpFilePath   = tempFileName;
                var tempFileName2 = Path.Combine(GetTempPath(), Path.GetRandomFileName());
                if (ZipUtils.IsL33TZipFile(tempFileName))
                {
                    ct.ThrowIfCancellationRequested();
                    //
                    progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 70,
                                                                   new ExLog(LogLevel.Info, "      - Extract downloaded file...")));

                    var extractProgress = new Progress <ZipFileProgress>();
                    if (progress != null)
                    {
                        extractProgress.ProgressChanged += (o, ea) =>
                        {
                            progress.Report(new ScanAndRepairFileProgress(fileInfo.FileName,
                                                                          70 + Convert.ToInt32(Math.Floor((double)ea.ProgressPercentage / 100 * (90 - 70))),
                                                                          ea));
                        }
                    }
                    ;
                    await ZipUtils.DoExtractL33TZipFile(tempFileName, tempFileName2, extractProgress, ct);

                    ct.ThrowIfCancellationRequested();
                    //#90 Check Downloaded File
                    if (!RunFileCheck(tempFileName2, fileInfo.Size, fileInfo.Crc32))
                    {
                        if (File.Exists(tempFileName))
                        {
                            File.Delete(tempFileName);
                        }

                        if (File.Exists(tempFileName2))
                        {
                            File.Delete(tempFileName2);
                        }

                        throw new Exception("Extracted file is invalid!");
                    }

                    tmpFilePath = tempFileName2;
                }
                else if (ZipUtils.IsL66TZipFile(tempFileName))
                {
                    ct.ThrowIfCancellationRequested();
                    //
                    progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 70,
                                                                   new ExLog(LogLevel.Info, "      - Extract downloaded file...")));

                    var extractProgress = new Progress <ZipFileProgress>();
                    if (progress != null)
                    {
                        extractProgress.ProgressChanged += (o, ea) =>
                        {
                            progress.Report(new ScanAndRepairFileProgress(fileInfo.FileName,
                                                                          70 + Convert.ToInt32(Math.Floor((double)ea.ProgressPercentage / 100 * (90 - 70))),
                                                                          ea));
                        }
                    }
                    ;
                    await ZipUtils.DoExtractL66TZipFile(tempFileName, tempFileName2, extractProgress, ct);

                    ct.ThrowIfCancellationRequested();
                    //#90 Check Downloaded File
                    if (!RunFileCheck(tempFileName2, fileInfo.Size, fileInfo.Crc32))
                    {
                        if (File.Exists(tempFileName))
                        {
                            File.Delete(tempFileName);
                        }

                        if (File.Exists(tempFileName2))
                        {
                            File.Delete(tempFileName2);
                        }

                        throw new Exception("Extracted file is invalid!");
                    }

                    tmpFilePath = tempFileName2;
                }

                ct.ThrowIfCancellationRequested();
                //#95 Move new file to game folder
                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 95,
                                                               new ExLog(LogLevel.Info, "      - Moving new file...")));

                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }

                var pathName = Path.GetDirectoryName(filePath);
                if (!string.IsNullOrEmpty(pathName) && !Directory.Exists(pathName))
                {
                    Directory.CreateDirectory(pathName);
                }

                File.Move(tmpFilePath, filePath);

                //#99 Removing temporary file
                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 99,
                                                               new ExLog(LogLevel.Info, "      - Clean-up temporary files...")));

                if (File.Exists(tmpFilePath))
                {
                    File.Delete(tmpFilePath);
                }

                if (File.Exists(tempFileName))
                {
                    File.Delete(tempFileName);
                }

                if (File.Exists(tempFileName2))
                {
                    File.Delete(tempFileName2);
                }

end:
                //#100
                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 100));
            }
            catch (AggregateException e)
            {
                progress?.Report(new ScanAndRepairFileProgress(fileInfo.FileName, 100,
                                                               new ExLog(LogLevel.Info, "-------------------------\r\n" +
                                                                         "!!! Error !!!\r\n" +
                                                                         "-------------------------\r\n" +
                                                                         $"{e.Message}")));

                return(false);
            }
            return(true);
        }
Exemple #4
0
        public static async Task <bool> ScanAndRepairFile(GameFileInfo fileInfo, string gameFilePath,
                                                          bool useChunkDownloader = false, IProgress <ScanSubProgress> progress = null,
#pragma warning disable IDE0034 // Simplifier l'expression 'default'
                                                          CancellationToken ct = default(CancellationToken))
#pragma warning restore IDE0034 // Simplifier l'expression 'default'
        {
            var filePath = Path.Combine(gameFilePath, fileInfo.FileName);

            //#1 Check File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Check, 0));

            Progress <double> subProgressCheck = null;

            if (progress != null)
            {
                subProgressCheck = new Progress <double>();
                subProgressCheck.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.Check, d));
                };
            }

            if (await RunFileCheck(filePath, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheck))
            {
                progress?.Report(new ScanSubProgress(ScanSubProgressStep.End, 100));
                return(true);
            }

            //#2 Download File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Download, 0));

            var tempFileName = Path.Combine(GameScannerTempPath, $"{fileInfo.FileName.GetHashCode():X4}.tmp");

            if (File.Exists(tempFileName))
            {
                File.Delete(tempFileName);
            }

            var fileDownloader = useChunkDownloader && fileInfo.BinSize > ChunkFileDownloader.ChunkSizeLimit
                ? new ChunkFileDownloader(fileInfo.HttpLink, tempFileName, GameScannerTempPath)
                : (IFileDownloader) new SimpleFileDownloader(fileInfo.HttpLink, tempFileName);

            if (progress != null)
            {
                fileDownloader.ProgressChanged += (sender, eventArg) =>
                {
                    switch (fileDownloader.State)
                    {
                    case FileDownloaderState.Invalid:
                    case FileDownloaderState.Download:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, fileDownloader.DwnlProgress * 0.99,
                                            new ScanDownloadProgress(fileDownloader.DwnlSize, fileDownloader.DwnlSizeCompleted,
                                                                     fileDownloader.DwnlSpeed)));
                        break;

                    case FileDownloaderState.Finalize:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 99,
                                            new ScanDownloadProgress(fileDownloader.DwnlSize, fileDownloader.DwnlSizeCompleted,
                                                                     0)));
                        break;

                    case FileDownloaderState.Complete:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 100,
                                            new ScanDownloadProgress(fileDownloader.DwnlSize, fileDownloader.DwnlSizeCompleted,
                                                                     0)));
                        break;

                    case FileDownloaderState.Error:
                    case FileDownloaderState.Abort:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(fileDownloader.State),
                                                              fileDownloader.State, null);
                    }
                }
            }
            ;

            try
            {
                await fileDownloader.Download(ct);
            }
            catch (Exception e)
            {
                throw new Exception($"Downloaded file '{fileInfo.FileName}' failed!\r\n" +
                                    $"{e.Message}");
            }

            //#3 Check Downloaded File
            ct.ThrowIfCancellationRequested();

            Progress <double> subProgressCheckDown = null;

            if (progress != null)
            {
                progress.Report(new ScanSubProgress(ScanSubProgressStep.CheckDownload, 0));

                subProgressCheckDown = new Progress <double>();
                subProgressCheckDown.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckDownload, d));
                };
            }

            if (!await RunFileCheck(tempFileName, fileInfo.BinSize, fileInfo.BinCrc32, ct, subProgressCheckDown))
            {
                if (File.Exists(tempFileName))
                {
                    File.Delete(tempFileName);
                }

                throw new Exception($"Downloaded file '{fileInfo.FileName}' is invalid!");
            }

            //#4 Extract downloaded file
            ct.ThrowIfCancellationRequested();
            if (L33TZipUtils.IsL33TZipFile(tempFileName))
            {
                var tempFileName2 = $"{tempFileName.Replace(".tmp", string.Empty)}.ext.tmp";
                //
                Progress <double> extractProgress = null;
                if (progress != null)
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.ExtractDownload, 0));

                    extractProgress = new Progress <double>();
                    extractProgress.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.ExtractDownload, d));
                    };
                }
                await L33TZipUtils.DoExtractL33TZipFile(tempFileName, tempFileName2, ct, extractProgress);

                //#4.1 Check Extracted File
                ct.ThrowIfCancellationRequested();
                Progress <double> subProgressCheckExt = null;
                if (progress != null)
                {
                    //
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckExtractDownload, 0));

                    subProgressCheckExt = new Progress <double>();
                    subProgressCheckExt.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.CheckExtractDownload, d));
                    };
                }

                if (!await RunFileCheck(tempFileName2, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheckExt))
                {
                    throw new Exception($"Extracted file '{fileInfo.FileName}' is invalid!");
                }

                tempFileName = tempFileName2;
            }

            //#5 Move new file to game folder
            ct.ThrowIfCancellationRequested();

            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.Finalize, 0));

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            else
            {
                var pathName = Path.GetDirectoryName(filePath);
                if (!string.IsNullOrEmpty(pathName) && !Directory.Exists(pathName))
                {
                    Directory.CreateDirectory(pathName);
                }
            }

            File.Move(tempFileName, filePath);

            //#6 End
            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.End, 100));

            return(true);
        }